如何匹配未转义的带引号的字符串以及非引号的字符串?

时间:2019-07-14 00:12:06

标签: javascript regex regex-lookarounds regex-group

我有一个包含单引号,双引号和转义引号的字符串:

  

自言自语“你是\'伟大\'”,然后说“谢谢”感觉“很“好”

我想要一个正则表达式:

  1. 单引号字符串
  2. 双引号字符串
  3. 字符串不在引号中

预期结果:以下分组

  1. 自我介绍
  2. 你是\'great \'
  3. 然后说
  4. 谢谢
  5. 感觉
  6. 一个“小”很好

要求:不要返回引号,而忽略转义的引号

我到目前为止所拥有的:

正则表达式1返回单引号和双引号(source):

((?<![\\])['"])((?:.(?!(?<![\\])\1))*.?)\1

结果: enter image description here

正则表达式2返回不带引号的字符串

((?<![\\])['"]|^).*?((?<![\\])['"]|$)

结果: enter image description here

问题:

  1. 我无法使正则表达式2将未引用的字符串放入一致的组中
  2. 我无法将regex#1和#2组合在一起以在一个regex函数中返回所有字符串

2 个答案:

答案 0 :(得分:2)

怎么样呢?

(?<!\\)'(.+?)(?<!\\)'|(?<!\\)"(.+?)(?<!\\)"|(.+?)(?='|"|$)

Demo

其背后的基本思想是,它尝试首先将带引号的字符串匹配,这样之后剩下的就是未用引号引起来的字符串。您将在捕获组中具有所有匹配的字符串(不包括引号)。

简化版

(?<!\\)(['"])(.+?)(?<!\\)\1|(.+?)(?='|"|$)

Demo


如果您不想使用捕获组,则可以对其进行调整以使其与以下环境类似:

(?<=(?<!\\)').+?(?=(?<!\\)')|(?<=(?<!\\)").+?(?=(?<!\\)")|(?<=^|['"]).+?(?=(?<!\\)['"]|$)

Demo

简化版

(?<=(?<!\\)(['"])).+?(?=(?<!\\)\1)|(?<=^|['"]).+?(?=(?<!\\)['"]|$)

Demo

答案 1 :(得分:2)

JS版本

/(?:"([^"\\]*(?:\\[\S\s][^"\\]*)*)"|'([^'\\]*(?:\\[\S\s][^'\\]*)*)'|([^'"\\]+)|(\\[\S\s]))/

https://regex101.com/r/5xfs7q/1


PCRE-Pro级,超级版本..

(?|(?|\s*((?:[^'"\\]|(?:\\[\S\s][^'"\\]*))+)(?<!\s)\s*|\s+(*SKIP)(*FAIL))|(?<!\\)(?|"([^"\\]*(?:\\[\S\s][^"\\]*)*)"|'([^'\\]*(?:\\[\S\s][^'\\]*)*)')|([\S\s]))

https://regex101.com/r/Tdyd3y/1

这是我见过的最干净,最漂亮的一个。 Wsp trim和regex仅包含一个捕获组。

解释

 (?|                           # 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
 )