• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 202
  • Last Modified:

string modifier function

I need to modify a series of strings containing e.g.

_123abc
__abc123
___abcxyz
xzy789_
_123abc_
789123___

to become e.g.:

_ 123abc
__ abc123
___ abcxyz
xzy789 _
_ 123abc _
789123 ___

So each last underscore on the front of the middle needs a space if it has one and on the end of the middle bit a space before the underscore if an underscore is there. If there is no underscore then no space is added.

I can do this using an inelegant for loop although there must be a better way.

I tried using preg_replace ereg_replace although the syntax isn't documented well enough for me to use it.


0
evcr
Asked:
evcr
  • 4
  • 4
1 Solution
 
SteveH_UKCommented:
Assuming a string is in $val, try:

$val = preg_replace('/^(_+)([^ ])/', '${1} ${2}', $val);
$val = preg_replace('/([^ ])(_+)$/', '${1} ${2}', $val);

or:

$patterns[0] = '/^(_+)([^ ])/';
$patterns[1] = '/([^ ])(_+)$/';
$reps[0] = '${1} ${2}';
$reps[1] = '${1} ${2}';
$val = preg_replace($patterns, $reps, $val);

0
 
evcrAuthor Commented:


Thanks that works fine although I forgot a bit....

each string has an associated string e.g.

a 123abc
bb abc123
ccc abcxyz
xzy789 1
z 123abc z
789123 cc

so I need to add the spaces in the same place as the strings with underscores...


0
 
SteveH_UKCommented:
The trick here is to define the pattern.

In these cases you would have:

'/(123abc)$/' --> ' ${1}'
'/(abc123)$/' --> ' ${1}'
'/(abcxyz)$/' --> ' ${1}'
'/^(xzy789)/' --> '${1} '
'/(.)(123abc)(.)/' --> '${1} ${2} ${3}'
'/^(789123)/' --> '${1} '

All of these can be placed in the patterns and reps arrays I previously suggested.  However, depending on the actual content of your strings you may need more sophisticated expressions to prevent one string matching more than once.  Also, if you intend the matching to be more general, you will need to use character sets such as:

[0-9]  or \d = a decimal digit
[a-zA-Z]  = alphabetic character

For the first test, for example:

'/^([a-zA-Z])([0-9][0-9][0-9][a-zA-Z][a-zA-Z][a-zA-Z])$/' --> '${1} ${2}'

which can be simplified to:

'/^([a-zA-Z])(\d{3}[a-zA-Z]{3})$/'  --> '${1} ${2}'

The {3} means match the previous character (or group or character set) exactly three times.
0
Learn to develop an Android App

Want to increase your earning potential in 2018? Pad your resume with app building experience. Learn how with this hands-on course.

 
evcrAuthor Commented:

yeah, thanks but I only know where to put the spaces based on where the underscores appear, e.g. if i have two arrays:

$arr1 = ['_123abc','__abc123','___abcxyz','xzy789_',_123abc_,'789123___'];

$arr1 = ['a123abc','123abc123','zx3abcxyz','xzy789z',a123abcz,'789123ab3'];

The result would need to be e.g.:

$arr1 = ['a 123abc','123 abc123','zx3 abcxyz','xzy789 z',a 123abc z,'789123 ab3'];

I couldn't see a way to get the positions of the underscores using regex, I realise using substr() in a for loop would work although it seems the wrong way to do it.


0
 
evcrAuthor Commented:
oops the second $arr1 is supposed to be $arr2
0
 
SteveH_UKCommented:
You could do it as follows:

1.  Loop through your arrays
2.  Construct patterns and replacements based on $arr1 using preg_match
3.  Use preg_replace using the patterns, replacements and the contents of $arr2

So...

$result = array();

foreach ($arr1 as $index => $a1) {
  $matches = array();
  preg_match('/^(_*)?([0-9A-Za-z]+)(_*)?$/', $a1, $matches);

  $len_p1 = strlen($matches[1]);
  $len_p2 = strlen($matches[2]);
  $len_p3 = strlen($matches[3]);
  $i = 1;
  $pattern = '/^';
  $replace = '';

  if ($len_p1 > 0) {
    $pattern .= '([A-Za-z0-9]{' . $len_p1 . '})';
    $replace .= '${' . $i . '} ';
    $i++;
  }
    $pattern .= '([A-Za-z0-9]{' . $len_p2 . '})';
    $replace .= '${' . $i . '}';
    $i++;
  if ($len_p3 > 0) {
    $pattern .= '([A-Za-z0-9]{' . $len_p3 . '})';
    $replace .= ' ${' . $i . '}';
    $i++;
  }
  $pattern .= '$/';

  $result[] = preg_replace($pattern, $replace, $arr2[$index]);
}
0
 
evcrAuthor Commented:

works a treat, thanks Steve.

0
 
SteveH_UKCommented:
You're welcome.  Glad we got it working for you :)

Do you understand the logic, or would you like me to explain it further?
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now