1
\$\begingroup\$

I would like to improve my preg_replace regex. This is to clean a features list.

I want allow for the begining of each line:

  • alphanumeric characters
  • == and alphanumeric characters
  • -- alphanumeric characters
  • ++ alphanumeric characters
  • ** alphanumeric characters

my regex:

$features = "
    == Category one
    → feature 1
    ++ feature 2
    -- feature 3
    ==-
    ! feature 4
    % feature 5";    

preg_replace('/' . 
          '^[^[:alnum:]]{0,}(==-.*)$' . '|' .              // ==-
          '^[^[:alnum:]]{0,}([\+|\-|\*|\=]{2}.*)$' . '|' . // ==
          '^[^[:alnum:]]{0,}(.*)$' .                       // abc
          '/mu', '$1$2$3', 
          $features);

Dirty features:

  • == Category one
  • → feature 1
  • ++ feature 2
  • -- feature 3
  • ==-
  • ! feature 4
  • % feature 5

Clean:

  • == Category one
  • feature 1
  • ++ feature 2
  • -- feature 3
  • ==-
  • feature 4
  • feature 5

It works, but i think there is a better way ... Thanks

\$\endgroup\$
  • \$\begingroup\$ Is $features the entire string - or has it already been separated for each line? Based off what I see in your Regexp - it looks like the entire string is in there. You may be better off just exploding your string by line and then compare the first 2 to 3 characters using a switch statement which would be a little cheaper to process me thinks \$\endgroup\$ – Duniyadnd Dec 3 '12 at 14:20
  • \$\begingroup\$ Thanks a lot ! It's really easier ! I'm going to work on it, i would like it transform something like -line1 -- line2 to line1 -- line2 refuse +|-|=|* without whitespace after ... \$\endgroup\$ – user20020 Dec 5 '12 at 9:09
  • \$\begingroup\$ Hi and welcome to the site. Unfortunately, this reads like a "please help me write better code" - which is off topic, rather then "please explain what is wrong with this code so I can improve it" - which would be on-topic. \$\endgroup\$ – Donald.McLean Jul 12 '19 at 14:47
2
\$\begingroup\$

Maybe this one : #^[^-=+*\w]{2}\s*#um (that is ~500% faster than yours):

<?php
$list = '
== Category one
→ feature 1
++ feature 2
-- feature 3
==-
! feature 4
% feature 5
** feature 6
feature 7';

$list = preg_replace('#^[^-=+*\w]{2}\s*#um', '', $list);
print_r($list);

Whose output is:

== Category one
feature 1
++ feature 2
-- feature 3
==-
feature 4
feature 5
** feature 6
feature 7

Subsidiary question

You can complete the regexp #^[^-=+*\w]{2}\s*#um by the regexp #^([-=+*])(?!\1|\s)#um to refuse +|-|=|* without whitespace after.

It is possible to combine the two regexps but at the expense of performance.

<?php
function printResult($label, $list, $start, $end) {
  printf(
    "%s: %F s\n%s\n\n",
    $label,
    $end - $start,
    print_r($list, true)
  );
}

$list = '== Category one
→ feature 1
++ feature 2
-- feature 3
==-
! feature 4
% feature 5
** feature 6
feature 7
-line1
-- line2';

// Case 1: regrouping the regexps
$time_start = microtime(true);
$list = preg_replace('#^[^-=+*\w]{2}\s*|^([-=+*])(?!\1|\s)#um', '', $list);
$time_end = microtime(true);
printResult('With one regexp', $list, $time_start, $time_end);

// Case 2: a faster way
$time_start = microtime(true);
$list = preg_replace('#^[^-=+*\w]{2}\s*#um', '', $list);
$list = preg_replace('#^([-=+*])(?!\1|\s)#um', '', $list);
$time_end = microtime(true);
printResult('In two pass, a faster way', $list, $time_start, $time_end);

Whose output is:

With one regexp: 0.000151 s
== Category one
feature 1
++ feature 2
-- feature 3
==-
feature 4
feature 5
** feature 6
feature 7
line1
-- line2

In two pass, a faster way: 0.000024 s
== Category one
feature 1
++ feature 2
-- feature 3
==-
feature 4
feature 5
** feature 6
feature 7
line1
-- line2

Note: preg_replace replaces the overall catch, therefore it is useless to try to capture the full line.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.