There is a task to delete the last line feed \n from the text if there are no characters behind it, or its own spaces followed by it, if there are no other characters except the spaces until the end of the text.

I use preg_replace () and the regular expression %\n\x20*$%

The test gives the expected behavior when replacing:

 $text = "abcd\n \n "; var_dump(preg_replace('%\n\x20*$%', '', $text, -1, $count), $count); var_dump(preg_replace('%\n\x20*$%', '', $text, 1, $count), $count); 

Result of work:

 string 'abcd ' (length=10) int 1 string 'abcd ' (length=10) int 1 

The test gives an unexpected result:

 $text = "abcd\n \n"; var_dump(preg_replace('%\n\x20*$%', '', $text, -1, $count), $count); var_dump(preg_replace('%\n\x20*$%', '', $text, 1, $count), $count); 

Result of work:

 string 'abcd' (length=4) <== замена прошла два раза, int 2 <== вместо одного как ожидалось string 'abcd ' (length=5) <== "съежены" пробелы до символа перевода строки, int 1 <== даже при выполнении всего 1ой замены 

Question : What is my mistake?

PS A similar regular expression for the beginning of the text works as expected in all cases.

  • Can you even need rtrim, and not a regular? - Small
  • @ Small, rtrim() no limit on the number of operations. - Visman

1 answer 1

By default, PCRE treats data as a single-line character string (even if it contains multiple line terminators). The metacharacter of the beginning of the string '^' matches only the beginning of the text being processed, while the metacharacter "end of the line" '$' corresponds to the end of the text or position before the final text of the line break (if the D modifier is not set).

Those. $ treated as the end of a string BEFORE \n if it is the last character.

In your case, you must use the modifier D

 $text = "abcd\n \n"; var_dump(preg_replace('%\n\x20*$%D', '', $text, -1, $count), $count); var_dump(preg_replace('%\n\x20*$%D', '', $text, 1, $count), $count); string(10) "abcd " int(1) string(10) "abcd " int(1)