substring max 25 chars,如果匹配模式,则保持字符串的结尾

I have a string that can be like this:

$string = 'namestring';

Or $string = 'namestring_1';

Namestring can be everything and can or not be followed by underscore + number.

I need to check if the string length is more of 25 chars and if it is truncate only the part of the namestring keeping the underscore+number if there is so the total length will be 25 chars.

Example:

$string ='012345678901234567890123456789_6';
$string2 ='012345678901234567890123456789';

Has to change in:

$string ='01234567890123456789012_6';
$string2 ='0123456789012345678901234';

Can you help me please?

Edit: Sorry...I didn't think to specify it. Not necessarily only one digit even if it is very rare for it to be two digits after the underscore.

I think this may be a working solution for you if only a single digit can follow after the underscore. Otherwise, you just need to modify it so 23 becomes 25 - strlen($match[1]).

if (preg_match('/(_\d)$/', $namestring, $match)) {
    $namestring = substr(0, 23, $namestring) . $match[1];
} else {
    $namestring = substr(0, 25);
}

The ugly regex solution from the mountain (for only 1 digit after the underscore):

$result = preg_replace('~^.{23}\K(?(?!.*_\d$)(.{2})).*(_\d)?$~', '$1$2', $str); 

Pattern detail:

I use a conditional inside (IF...THEN...): (?(?!.*_\d$)(.{2}))

(?             # IF
  (?!.*_\d$)   # (CONDITION): if there is not _\d at the end
  (.{2})       # THEN: capture two other characters
)              # ENDIF

or better with a branch reset (?|..|..):

$result = preg_replace('~^\d{23}\K(?|.*(_\d)|(.{2}).*)$~', '$1', $str);
$string ='012345678901234567890123456789_6';
$string2 ='012345678901234567890123456789';
$string3 ='0123456_78901234567890123456789';
$c = explode("_", $string, 2);
$fixed = (count($c) > 1 ? (((strlen($c[0]) > 23) ? (substr($c[0],0,strlen($c[0]))) : substr((substr($c[0],0,23) . "_" . $c[1]),0,25))) : substr($c[0],0,25));

This works regardless of what the input.

Output

  • For $string = "01234567890123456789012_6"
  • For $string2 = "0123456789012345678901234"
  • For $string3 = "0123456_78901234567890123"

Why not use substr()? Here is how I would do it:

$str= "67676767676767676766767675757675757575757575746655_2";
$pos = strpos($str,"_");

$end = substr($str, $pos-strlen($str));

$start = substr($str, 25-strlen($pos));

$your_string = $start.$end;

Edit: from all 4 answers, only mine would work if you have a 2-digit figure after the _ :)