这个问题有点麻烦,但正则表达式确实是可以一次做到的。
留意到引号不分左右,所以不会嵌套,如果要取出引号外的成分,可以先将原字符串对引号做一次split,然后取出单数(一起,如零起则双数)下标的子字符串。
按照这个思路,可以直接判断模式前后各有多少引号,仅当均有双数个引号时留下,此时模式在引号之外。事实上这就是判断平面上一点是否位于一多边形之内的射线法的思路。
考虑以下例子:
```
"hello hello" "hello" hello "hello" hello hello "hello"
```
此时引号外的`hello`只有第四、六、七个(一起),其他的都在引号之内,不要。要恰好找到它们,对应的完整正则表达式是:
```
(?<=([^"]*"[^"]*")*[^"]*$)hello(?=([^"]*"[^"]*")*[^"]*$)
```
但这里有个危险:在负向零宽断言中出现了不定量词。有的环境会将以上式子判断为不合法。如果能够保证整句的引号匹配(即总共有双数个),那么可以只留下后面一半(因为后面有双数个引号等价于前面也有双数个),即
```
hello(?=([^"]*"[^"]*")*[^"]*$)
```