如何匹配非转义引号字符串和非引号字符串?
How to match non-escaped quoted strings and also non-quoted strings?
我有一个包含单引号、双引号和转义引号的字符串:
Telling myself 'you are \'great\' ' and then saying "thank you" feels "a \"little\" nice"
我想要一个单一的正则表达式:
- 单引号字符串
- 双引号字符串
- 不在引号中的字符串
预期结果:以下组
- 告诉自己
- 你是\'great\'
- 然后说
- 谢谢
- 感觉
- 一个\"little\"不错
要求:不要 return 引号,并忽略转义引号
我目前有:
正则表达式 #1 到 return 单引号和双引号 (source):
((?<![\])['"])((?:.(?!(?<![\])))*.?)
结果:
正则表达式 #2 到 return 非引号字符串:
((?<![\])['"]|^).*?((?<![\])['"]|$)
结果:
问题:
- 我无法使正则表达式 #2 将非引号字符串放入一致的组中
- 我无法将正则表达式 #1 和 #2 合并到 return 一个正则表达式函数中的所有字符串
这样的事情怎么样:
(?<!\)'(.+?)(?<!\)'|(?<!\)"(.+?)(?<!\)"|(.+?)(?='|"|$)
Demo.
这背后的基本思想是,它首先尝试将字符串与引号匹配,这样之后剩下的就是没有被引号括起来的字符串。您将在捕获组中拥有所有匹配的字符串(不包括引号)。
简化版:
(?<!\)(['"])(.+?)(?<!\)|(.+?)(?='|"|$)
Demo.
如果您不想使用捕获组,您可以调整它以使用 Lookarounds,如下所示:
(?<=(?<!\)').+?(?=(?<!\)')|(?<=(?<!\)").+?(?=(?<!\)")|(?<=^|['"]).+?(?=(?<!\)['"]|$)
Demo.
简化版:
(?<=(?<!\)(['"])).+?(?=(?<!\))|(?<=^|['"]).+?(?=(?<!\)['"]|$)
Demo.
JS 版本
/(?:"([^"\]*(?:\[\S\s][^"\]*)*)"|'([^'\]*(?:\[\S\s][^'\]*)*)'|([^'"\]+)|(\[\S\s]))/
https://regex101.com/r/5xfs7q/1
PCRE - 专业级,超级版..
(?|(?|\s*((?:[^'"\]|(?:\[\S\s][^'"\]*))+)(?<!\s)\s*|\s+(*SKIP)(*FAIL))|(?<!\)(?|"([^"\]*(?:\[\S\s][^"\]*)*)"|'([^'\]*(?:\[\S\s][^'\]*)*)')|([\S\s]))
https://regex101.com/r/Tdyd3y/1
这是我见过的最干净、最好的。
Wsp trim 和正则表达式只包含一个捕获组。
已解释
(?| # BReset
(?| # BReset
\s* # Wsp trim
( # (1 start), Non-quoted data
(?:
[^'"\]
| (?: \ [\S\s] [^'"\]* )
)+
) # (1 end)
(?<! \s )
\s* # Wsp trim
| # or,
\s+ (*SKIP) (*FAIL) # Skip intervals with all whitespace
)
|
(?<! \ ) # Not an escape behind
(?| # BReset
"
( # (1 start), double quoted string data
[^"\]*
(?: \ [\S\s] [^"\]* )*
) # (1 end)
"
| # or,
'
( # (1 start), single quoted string data
[^'\]*
(?: \ [\S\s] [^'\]* )*
) # (1 end)
'
)
|
( [\S\s] ) # (1), Pass through, single char
# Un-balanced " or ' or \ at EOF
)
我有一个包含单引号、双引号和转义引号的字符串:
Telling myself 'you are \'great\' ' and then saying "thank you" feels "a \"little\" nice"
我想要一个单一的正则表达式:
- 单引号字符串
- 双引号字符串
- 不在引号中的字符串
预期结果:以下组
- 告诉自己
- 你是\'great\'
- 然后说
- 谢谢
- 感觉
- 一个\"little\"不错
要求:不要 return 引号,并忽略转义引号
我目前有:
正则表达式 #1 到 return 单引号和双引号 (source):
((?<![\])['"])((?:.(?!(?<![\])))*.?)
结果:
正则表达式 #2 到 return 非引号字符串:
((?<![\])['"]|^).*?((?<![\])['"]|$)
结果:
问题:
- 我无法使正则表达式 #2 将非引号字符串放入一致的组中
- 我无法将正则表达式 #1 和 #2 合并到 return 一个正则表达式函数中的所有字符串
这样的事情怎么样:
(?<!\)'(.+?)(?<!\)'|(?<!\)"(.+?)(?<!\)"|(.+?)(?='|"|$)
Demo.
这背后的基本思想是,它首先尝试将字符串与引号匹配,这样之后剩下的就是没有被引号括起来的字符串。您将在捕获组中拥有所有匹配的字符串(不包括引号)。
简化版:
(?<!\)(['"])(.+?)(?<!\)|(.+?)(?='|"|$)
Demo.
如果您不想使用捕获组,您可以调整它以使用 Lookarounds,如下所示:
(?<=(?<!\)').+?(?=(?<!\)')|(?<=(?<!\)").+?(?=(?<!\)")|(?<=^|['"]).+?(?=(?<!\)['"]|$)
Demo.
简化版:
(?<=(?<!\)(['"])).+?(?=(?<!\))|(?<=^|['"]).+?(?=(?<!\)['"]|$)
Demo.
JS 版本
/(?:"([^"\]*(?:\[\S\s][^"\]*)*)"|'([^'\]*(?:\[\S\s][^'\]*)*)'|([^'"\]+)|(\[\S\s]))/
https://regex101.com/r/5xfs7q/1
PCRE - 专业级,超级版..
(?|(?|\s*((?:[^'"\]|(?:\[\S\s][^'"\]*))+)(?<!\s)\s*|\s+(*SKIP)(*FAIL))|(?<!\)(?|"([^"\]*(?:\[\S\s][^"\]*)*)"|'([^'\]*(?:\[\S\s][^'\]*)*)')|([\S\s]))
https://regex101.com/r/Tdyd3y/1
这是我见过的最干净、最好的。 Wsp trim 和正则表达式只包含一个捕获组。
已解释
(?| # BReset
(?| # BReset
\s* # Wsp trim
( # (1 start), Non-quoted data
(?:
[^'"\]
| (?: \ [\S\s] [^'"\]* )
)+
) # (1 end)
(?<! \s )
\s* # Wsp trim
| # or,
\s+ (*SKIP) (*FAIL) # Skip intervals with all whitespace
)
|
(?<! \ ) # Not an escape behind
(?| # BReset
"
( # (1 start), double quoted string data
[^"\]*
(?: \ [\S\s] [^"\]* )*
) # (1 end)
"
| # or,
'
( # (1 start), single quoted string data
[^'\]*
(?: \ [\S\s] [^'\]* )*
) # (1 end)
'
)
|
( [\S\s] ) # (1), Pass through, single char
# Un-balanced " or ' or \ at EOF
)