I'm getting user submitted text from a <textarea></textarea>
, and I want to edit it a bit before storing it in a database. Here are my 3 regexes, with explanations below them:
/(?:^((\pZ)+|((?!\R)\pC)+)(?1)*)|((?1)$)|(?:((?2)+|(?3)+)(?=(?2)|(?3)))/um
- For every line...
- Match all leading whitespace and unicode control characters ("WS/CC") (EXCEPT LINE BREAKS).
- Match all trailing WS/CC (EXCEPT LINE BREAKS).
- Match all but one WS/CC between non-whitespace characters.
- regex101
- For every line...
/(\pZ+)|((?!\R)\pC)/u
- Match remaining WS/CC (EXCEPT LINE BREAKS).
- regex101
/(^\R+)|(\R+$)|(\R(?=\R{2}))/u
- Match all leading line breaks.
- Match all trailing line breaks.
- Match all but 2 consecutive line breaks.
- regex101
This is pretty much how I'm planning on using these regexes in my PHP script
// ...
// [Get user input from $_POST
// check its length, etc.,
// if everything looks O.K., store it in $str]
// ...
// Trim unnecessary whitespace (leave line breaks)
$str = preg_replace("/(?:^((\pZ)+|((?!\R)\pC)+)(?1)*)|((?1)$)|(?:((?2)+|(?3)+)(?=(?2)|(?3)))/um", '', $str);
// Convert remaining whitespace to regular spaces (leave line breaks)
$str = preg_replace("/(\pZ+)|((?!\R)\pC)/u", ' ', $str);
// Trim line breaks
$str = preg_replace("/(^\R+)|(\R+$)|(\R(?=\R{2}))/u", '', $str);
// Sanitize for safe printing between html tags
$str = htmlspecialchars($str, ENT_HTML5, 'UTF-8');
// ...
// [Store $str in DB with prepared statements]
// ...
And here's a test case which I've executed on regex101:
Input
(with some WS/CC in it):
a b c
d e
fghi j
k l m n
op
Output after 1st regex
(still has some WS/CC, but none consecutive, except for line breaks):
a b c
d e
fghi j
k l m n
op
Output after 2nd regex
(all previous WS/CC - except for line breaks - are now regular spaces):
a b c
d e
f g h i j
k l m n
o p
Output after 3rd regex
(max 2 consecutive line breaks, and no whitespace other than non-consecutive regular spaces):
a b c
d e
f g h i j
k l m n
o p
Based on my testing, this process seems to work as intended. I would however be very interested if you can think of any cases in which it would fail to behave as expected.
Also - in addition to possible fail-cases - I'd like to know if there are ways I could make these regexes perform better (faster), while still keeping the functionality as is. This is pretty much the first time I've ever done anything in regex, so I'm assuming there's some room for optimizations.
And if you see something else that is done incorrectly/could be done better, do let me know.
EDIT: Added regex101 links
EDIT2: Also, I've heard there's something called ReDoS, or Regex DoS. If you can tell that these regexes are susceptible to those, and which ones specifically, I'd like to know how to avoid them.
preg_replace()
can handle arrays for patterns and replacement parameters. \$\endgroup\$preg_replace
statements. This version might work, too, but it is still quite verbose. \$\endgroup\$