How to change nested quotes?

I'm looking for a way to change quotes for fancy: "abc"«abc» .

It works for me in simple situations, and the next step I'm looking for is to make it work with enclosed quotes: "abc "def" ghi"«abc «def» ghi»

 $pk =~ s/ "( # first qoute, start capture [\p{Word}\.]+? # at least one word-char or point .*?\b[\.,?!]*? # any char followed boundary + opt. punctuation )" # stop capture, ending quote /«$1»/xg; # change to fancy 

I was hoping that the regex would match the first and third quotes and modify them. And so it is. The problem is this: I hoped that I would repeat the second and fourth, but that would not be because the 2nd was already left behind. One solution is to repeat the same replacement until there are less than two quotation marks in it.

Is there a better way to achieve my goal? My approach will not work when there is a third level of nesting, and this is not my goal, I remain with two levels.


NB! Changing the start code and questionnaires in a separate replacement will not work, because then single double quotes will be replaced. I need to replace only when they appear as a couple!

MORE examples:

 "abc "def" -> «abc "def» "abc"def" -> «abc"def» 

This seems impossible:

 "abc" def" -> «abc" def» 
+2
regex perl
source share
2 answers

There is no general way to pair nested double quotes. If your quotes are always near the beginning or end of a word, this might work. It replaces the double quote that precedes the non-spatial character with an open quote, and the one that succeeds in the non-spatial character with a closed quote.

 use strict; use warnings; use utf8; my $string = '"abc "def" ghi"'; $string =~ s/"(?=\S)/«/g; $string =~ s/(?<=\S)"/»/g; print $string; 

Exit

 «abc «def» ghi» 
+2
source share

You can use negative search statements to find relevant directions in your quotes. Double negatives help handle boundary cases (e.g. end / beginning of line). I used << and >> instead of your fancy quotes here for simplicity.

 use strict; use warnings; while (<DATA>) { s/(?<!\S)"(?!\s)/<</g; s/(?<!\s)"(?!\S)/>>/g; print; } __DATA__ "abc "def" ghi" 

Output:

 <<abc <<de f>> ghi>> 
+2
source share

All Articles