1

I have some strings like this:

i: 11;a:5: {s:2:"id";s:4:"1097";s:5:"iName";s:12:"Ovo de Andre";s:10:"dropChance";s:4:"2000";s:4:"type"; i:1;s:5: "kName"; s:12: "Ovo de Andre";

And, I'd like to know how I could replace that string: "Ovo de Andre" to something like this:

"Ovo_de_Andre", but it can't change any spaces that could be out "".

I tried:

$string = preg_replace('/"(.?)\s(.?)"/m', '"$1_$2"', $string);

But it just replaces the first space, then the string looks like this:

i: 11;a:5: {s:2:"id";s:4:"1097";s:5:"iName";s:12:"Ovo_de Andre";s:10:"dropChance";s:4:"2000";s:4:"type"; i:1;s:5: "kName"; s:12: "Ovo_de Andre";

I know I could use a while to check it, but it'd be problematic to performance and I think it'd would be redundant.

Additionally, I want to know how could it be to make the same, but rather than replacing spaces within "", replace those out, without change spaces within "".

Thanks in advance.


I have this link that makes something similar but I couldn't manage what changing to make it reach what i want: Using preg_replace to replace all occurrences in php.

Here is the full data, I separeted it in strings to test one by one looking for errors that were there.

$string = 'a:16:{'; $string .= ' i:0;a:5:{s:2:"id";s:4:"1113";s:5:"iName";s:5:"Drops";s:10:"dropChance";s:4:"7500";s:4:"type";i:1;s:5:"kName";s:5:"Drops";}'; $string .= 'i:1;a:5:{s:2:"id";s:4:"1585";s:5:"iName";s:11:"Mime Monkey";s:10:"dropChance";s:4:"7000";s:4:"type";i:1;s:5:"kName";s:11:"Mime Monkey";}'; $string .= 'i:2;a:5:{s:2:"id";s:4:"1027";s:5:"iName";s:7:"Raptice";s:10:"dropChance";s:4:"7000";s:4:"type";i:1;s:5:"kName";s:7:"Raptice";}'; $string .= 'i:3;a:5:{s:2:"id";s:4:"1002";s:5:"iName";s:6:"Poring";s:10:"dropChance";s:4:"7000";s:4:"type";i:1;s:5:"kName";s:6:"Poring";}'; $string .= 'i:4;a:5:{s:2:"id";s:4:"1767";s:5:"iName";s:8:"Deviling";s:10:"dropChance";s:4:"5000";s:4:"type";i:2;s:5:"kName";s:8:"Deviling";}'; $string .= 'i:5;a:5:{s:2:"id";s:4:"1767";s:5:"iName";s:8:"Deviling";s:10:"dropChance";s:4:"5000";s:4:"type";i:2;s:5:"kName";s:8:"Deviling";}'; $string .= 'i:6;a:5:{s:2:"id";s:4:"1766";s:5:"iName";s:8:"Angeling";s:10:"dropChance";s:4:"5000";s:4:"type";i:2;s:5:"kName";s:8:"Angeling";}'; $string .= 'i:7;a:5:{s:2:"id";s:4:"1766";s:5:"iName";s:8:"Angeling";s:10:"dropChance";s:4:"5000";s:4:"type";i:2;s:5:"kName";s:8:"Angeling";}'; $string .= 'i:8;a:5:{s:2:"id";s:4:"1004";s:5:"iName";s:6:"Zangão";s:10:"dropChance";s:4:"3500";s:4:"type";i:1;s:5:"kName";s:6:"Zangão";}'; $string .= 'i:9;a:5:{s:2:"id";s:4:"1236";s:5:"iName";s:12:"Ovo de Andre";s:10:"dropChance";s:4:"3000";s:4:"type";i:1;s:5:"kName";s:12:"Ovo de Andre";}'; $string .= 'i:10;a:5:{s:2:"id";s:4:"1076";s:5:"iName";s:9:"Esqueleto";s:10:"dropChance";s:4:"3000";s:4:"type";i:1;s:5:"kName";s:9:"Esqueleto";}'; $string .= 'i:11 ;a:5: {s:2:"id";s:4:"1097";s:5:"iName";s:12:"Ovo de Andre";s:10:"dropChance";s:4:"2000";s:4:"type";i:1;s:5:"kName";s:12:"Ovo de Andre";}'; $string .= 'i:12;a:5:{s:2:"id";s:4:"1051";s:5:"iName";s:14:"Besouro-Ladrão";s:10:"dropChance";s:4:"2000";s:4:"type";i:1;s:5:"kName";s:14:"Besouro-Ladrão";}'; $string .= 'i:13;a:5:{s:2:"id";s:4:"1183";s:5:"iName";s:16:"ChonChon Raivoso";s:10:"dropChance";s:4:"1500";s:4:"type";i:1;s:5:"kName";s:16:"ChonChon Raivoso";}';
$string .= 'i:14;a:5:{s:2:"id";s:4:"1011";s:5:"iName";s:8:"ChonChon";s:10:"dropChance";s:4:"1500";s:4:"type";i:1;s:5:"kName";s:8:"ChonChon";}'; $string .= 'i:15;a:5:{s:2:"id";s:4:"1784";s:5:"iName";s:5:"Stapo";s:10:"dropChance";s:4:"1000";s:4:"type";i:1;s:5:"kName";s:5:"Stapo";}'; $string .= '}';

If looked carefully you'll notice in the lines i:0 and i:11 of the vector some spaces between the data that shows what line number and size of data exists.

5
  • 2
    This looks like a serialized array, why don't you deserialize it first? Anyways, if you just want to replace spaces, then there is not need for a regular expression. Have a look at str_replace. Commented Mar 11, 2012 at 17:48
  • str_replace would replace spaces out of "" so it would break this string, as it's not a perfect serialized one, this function I'm asking for would remove spaces that are out of true serialized strings to make it a correct serialized one. Commented Mar 11, 2012 at 17:52
  • Ok @Marcelo - I see here you have clarified that you don't have a valid serialized object. Disregard my answer then! Commented Mar 11, 2012 at 18:01
  • @kissmyface seems to me though, that it would be much simpler to turn this into a valid serialized object than to use some convoluted regular expression Commented Mar 11, 2012 at 18:03
  • @andrewtweber If you mean modifying the string to add to it what it needs in order to become a valid serialized object then I would tend to agree with you. However without seeing the raw data I can't make that call - there might not be a standard way to do that across all values. Commented Mar 11, 2012 at 18:08

3 Answers 3

2

This should work:

$str = <<< EOF
i: 11;a:5: {s:2:"id";s:4:"1097";s:5:"iName";s:12:"Ovo de Andre";s:10:"dropChance";s:4:"2000";s:4:"type"; i:1;s:5: "kName"; s:12: "Ovo de Andre"
EOF;
$str = preg_replace_callback('#("[^"]*")#',
       create_function('$m',
          'return str_replace(" ", "_", $m[1]);'),
       $str);
echo $str . "\n";

Update: Since OP likes to have this replacement with single regex only, here is one using negative lookahead:

$str = preg_replace('#\s(?!([^\"]*\"[^\"]*\")*[^\"]*$)#', '_', $str);
echo $str . "\n";

In short this regex finds a space which is NOT followed by even number of double quotes, which means found space is within double quotes hence it is replaced by under-score.

OUTPUT:

i: 11;a:5: {s:2:"id";s:4:"1097";s:5:"iName";s:12:"Ovo_de_Andre";s:10:"dropChance";s:4:"2000";s:4:"type"; i:1;s:5: "kName"; s:12: "Ovo_de_Andre"
Sign up to request clarification or add additional context in comments.

3 Comments

It worked like a charm, thanks, but I whish it could be a way where I don't need callback to do it. Just like in this post: stackoverflow.com/questions/4643442/…
IMO if something can be achieved with a simple and maintainable code then why strive for complicated solution. There is reason why you haven't got any answer here doing it in straight preg_replace call and there is a reason why PHP dev team came up with preg_replace_callback. This is the case where preg_replace_callback should be used. btw I have already upvoted your question so can't up vote again :)
@Marcelo: Pls see my Update for single regex based solution.
1

Edit: OP has clarified that the string is not a valid serialized object...

I'm not sure if you will be manipulating this object further, or where it came from, but the first thing I would do if it was me is unserialize it (this is making the assumption that you have a serialised object there: it certainly looks like it, although the exact string you posted is not a valid serialized object. I'm making the assumption that you didn't post the whole string).

http://www.php.net/manual/en/function.unserialize.php

Once you have your array in a sensible format you can start applying your transformations on a per attribute basis...

//unserialize
$person = unserialize($yourstring);

// now perfrom transformations
$person['iName'] = str_replace(' ', '_', $person['iName']);
$person['kName'] = str_replace(' ', '_', $person['kName']);
// etc...

// now re-serialize 
$person = serialize($person);

Performing masses of transformation on attributes of an object/array using regex is just a nightmare - make it easy on yourself and use php native functionality to help you!

If you dont have a serialised object then disregard this answer.

1 Comment

This would not fit as it's not a perfect serialized object.
0

I would avoid using regex if possible, because you can easily unserialize and read the value, then serialize it back. This will ensure that you know exactly what you're changing.

http://www.php.net/manual/en/function.unserialize.php

function space_to_underscore($str) {
    return str_replace(' ', '_', $str);
}

1 Comment

I can't unserialize because it has spaces between data-key that specifies how much data there is and where the value begins.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.