1

I need a regular expression to find , where they occur within any ' string '. I tried #'([[^'],])*'# but this didn't work. What's the simplest way to achieve this so I can replace them. Thanks.

Example:

$str = "(1,2132,'hello world 1, (this is to force it) & another, comma')";

$value_str = preg_replace("#'([[^'],])*'#",'C_1',$str);

Expected output:

'hello world 1C_1 (this is to force it) & anotherC_1 comma'
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
Antony
  • 3,875
  • 30
  • 32
  • 1
    `(,)` - but really a string replace would be less overhead (instead of regex) https://regex101.com/r/vB6vX0/1 – ʰᵈˑ Mar 16 '15 at 09:49
  • post a long example along with expected output. – Avinash Raj Mar 16 '15 at 09:49
  • 1
    for just finding a single character in a string, pretty much whatever language you use will have a built in function for this – Simon Mar 16 '15 at 09:50
  • what is your expected output? – anubhava Mar 16 '15 at 09:53
  • I would hope for 'hello world 1C_1 (this is to force it) & anotherC_1 comma' – Antony Mar 16 '15 at 09:54
  • @Antony provide the exact expected output. – Avinash Raj Mar 16 '15 at 10:05
  • @runDOSrun `str_replace` will replace all the commas. – Avinash Raj Mar 16 '15 at 10:08
  • @Antony Do you have to do it in a single replace? How about first getting the text between single quotes, then replace the commas there? – Jerry Mar 16 '15 at 10:11
  • @runDOSrun he don't want to touch the commas which are present outside the quotes. – Avinash Raj Mar 16 '15 at 10:15
  • @Jerry - yes not a bad idea. I had expected it to be easier through regex. Also I don't believe this question is a duplicate as this is inside quotes not outside. – Antony Mar 16 '15 at 10:17
  • @Antony Is that easier? http://ideone.com/4EZ6W5 – Jerry Mar 16 '15 at 10:17
  • @Jerry - yes it probably is. Question though - is it more efficient to do it all in 1 single call like the preg_replace or is it better to do a find, loop, replace? I had expected the pattern to be quite easy but I'm not sure how slower the answer pattern would be v the foreach you've suggested. – Antony Mar 16 '15 at 10:23
  • @Antony The lookahead that the single regex uses is usually expensive. It goes forward then comes back at its initial point many times; might as just consider it as a long loop. And if you have many text between quotes, a callback might be more efficient (so you use a single function instead of looping to get all the text between quotes): [updated](http://ideone.com/3CRbAR). (also, I'm not sure if you want the original text back or only the quoted text....) – Jerry Mar 16 '15 at 10:28
  • @Jerry - thanks. I will actually use your code because I also need to tackle ( ) in a string which makes sense doing it in chunks like that. I'm trying to parse a mysql insert statement which may or may not have multiple value parts. – Antony Mar 16 '15 at 10:30
  • @Antony Ok cool. Glad I could help :). If you want to replace both at the same time, you can simply change the regex in the code from `"#'[^']*'#"` to `"#'[^']+'|\([^()]+\)#"` though you will need to be careful around nested parens. This regex takes only parens without nested ones, a regex that does will take the complexity up by quite a level (and speed will suffer accordingly). – Jerry Mar 16 '15 at 10:35

1 Answers1

1

You can use this lookahead based regex:

$str = "(1,2132,'hello world 1, (this is to force it) & another, comma')";
$value_str = preg_replace("#(?!(([^']*'){2})*[^']*$),#", 'C_1', $str);
//=> (1,2132,'hello world 1C_1 (this is to force it) & anotherC_1 comma')

(?!(([^']*'){2})*[^']*$) is a lookahead that makes sure comma is not followed by even number of single quotes.

anubhava
  • 761,203
  • 64
  • 569
  • 643