0

Here is my current pattern:

/([^\s])"([^\s])/

And here is the current example:

$str = 'this i"s a "test" word i"s"s';

And there is the current result: (replaced with $1$2)

$str = 'this is a "test" word is"s';

And here is the expected result:

$str = 'this is a "test" word iss';

How can I do that?

Martin AJ
  • 6,261
  • 8
  • 53
  • 111
  • 1
    Your solution does not work because multiple regex matches can't overlap. Once it matches the i"s, the next part is "s, which does not match. See for example: https://stackoverflow.com/questions/20833295/how-can-i-match-overlapping-strings-with-regex – Martin Cook Aug 01 '18 at 21:06
  • Near duplicates: https://stackoverflow.com/q/22354095/2943403 and https://stackoverflow.com/q/33997355/2943403 and https://stackoverflow.com/q/14138533/2943403 – mickmackusa Aug 02 '18 at 07:42

3 Answers3

4

Use this lookahead and lookbehind regex for search:

/(?<!\s)"(?!\s)/

and replace with empty string.

RegEx Demo

RexEx Details:

  • (?<!\s): Negative lookbehind to assert that we don't have a whitespace at previous position
  • ": Match a double quote
  • (?!\s): Negative lookahead to assert that we don't have a whitespace ahead.
anubhava
  • 761,203
  • 64
  • 569
  • 643
0

I would be using word boundaries for your sample input and expected result. No lookarounds and no capture groups necessary.

Code: (Demo)

$str = 'this i"s a "test" word i"s"s';
echo preg_replace('~\b"\b~', '', $str);

Output:

this is a "test" word iss

Sometimes users on Stackoverflow ask for one specific thing, but are actually open to different interpretations -- this is the reason for me stretching the interpretation of the question requirements. It may help the OP and/or it may help future readers.

Or if we are being super literal, then this pattern is best for matching double quotes that are neither preceded or followed by spaces: ~(?<! )"(?! )~

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • 1
    This works for provided sample input but as you said it is just a sample. The whole requirement, I think, lies in question's title: *How to select all `"` that don't have any space in its back and front?* – revo Aug 01 '18 at 21:06
  • 1
    @mickmackusa You are absolutely right. What's a good and valid answer depends largely on how narrow or open the question is interpreted. The regex tag often favors narrow (and ready to copy-and-paste) answers. – wp78de Aug 02 '18 at 08:10
0

I suggest to use the more flexible trash can approach:

\s"\S+"(\p{P}|\s)|(")

Demo

I use a capture group to search the good cases, the double quotes in question go into the trash bin.

It helps to deal with special cases, e.g. as shown here, with punctuation at the end. But it is easy to add more cases to exclude. See: http://www.rexegg.com/regex-best-trick.html

Sample Code:

$re = '/(\s"\S+"(?:\p{P}|\s))|"/';
$str = 'this i"s a "test" word i"s"s. NOt a "test".';
$subst = '$1';

$result = preg_replace($re, $subst, $str);
echo $result;

Output: this is a "test" word iss. NOt a "test".

wp78de
  • 18,207
  • 7
  • 43
  • 71
  • 1
    Fancy name but I doubt even if @CasimiretHippolyte uses this approach here. That doesn't work on [`this is a "test"" but ...`](https://regex101.com/r/w8TU3d/3) either. – revo Aug 01 '18 at 21:23
  • @revo I think the name just describe what it does but I would not consider it canonical. There are always edge cases. This is why I suggested this approach - not the specific pattern I showed in the sample, e.g. the punctuation case does not work with anubhava's suggestion. https://regex101.com/r/52wsov/7 – wp78de Aug 01 '18 at 21:39