【问题标题】:Regular expression to match string operator匹配字符串运算符的正则表达式
【发布时间】:2015-07-31 03:52:12
【问题描述】:

我正在尝试创建一个匹配运算符 ^ (xor) 的正则表达式,只要它充当两个字符串之间的运算符而不是字符串的一部分。

例如,有一个包含这两行的文件:

'asdfasdf'; 'asdfasd'^'asdflkj';
['asdf', '^', 'asdf'];

只有第一个应该匹配,因为它是唯一一个 ^ 不是字符串的一部分。当 ^ 不在字符串中时,如何使正则表达式匹配 ^?

更新:我正在使用 egrep。我需要一种方法来确定 ^ 何时是字符串的一部分或何时不是。我的最终目标是找出 xor 运算符何时用于字符串:类似于 ('[^']'\^.+|.+\^'[^']') 但这与我的示例的第二行匹配。

所以,它应该匹配如下字符串:

  'asdf1524-sdfaA'^'sdfa322='
  'sdfa22_'^$myvar
  $myvar^'asAf34%'

但是它不应该匹配:

 ['+','*','^','%']
 '^'=>2
 "afa^sadfa"

UPDATE2:又添加了一个示例来说明为什么建议的 awk 解决方案不起作用。在使用单引号字符串进行操作时,我需要找到 ^ 运算符。我想在一个文件中找到这个的出现次数,我想在一个 bash 脚本中添加这个检查。

提前致谢!

【问题讨论】:

  • 您似乎正在尝试解析一些代码。您的文件是用什么语言编写的?我确信正则表达式可以在大多数情况下工作,但我认为最可靠的方法是正确解析语言。
  • 您好,感谢您的回答。我正在尝试解析 PHP 代码。
  • 我怀疑这超出了正则表达式的能力。寻找一个 PHP 解析器来帮助你。
  • 不要使用 cmets 更新您的问题。相反,edit 您的问题提供了这些详细信息。
  • 谢谢,我绝对是这方面的菜鸟。

标签: regex bash grep


【解决方案1】:

像这样:^[^^,]+?(?<!')'?\^'?(?!')[^^,]+?$ 应该做你想做的事。 here 提供了一个示例。

【讨论】:

  • ''o'^'o'' 呢?
  • 感谢您的回答。我发布的代码只是一个例子。实际上我尝试了类似的方法:'[^']+'\^'[^']+' 但由于某种原因,它不适用于 grep 命令。此外,此示例不适用于 $myvar^'asdfads123' 之类的内容。当^ 不是字符串的一部分时,我需要匹配它。
  • @dbranco:您能否更改您的问题以包含更多示例?
  • 不幸的是,我似乎无法编辑我的问题(我认为我没有足够的声誉:()
  • @dbranco: 请把它们作为评论包括在内:)
【解决方案2】:

您要做的是明确catch 可能包含您不想匹配的^ 的字符串,然后丢弃那个字符串。 here 和 JavaScript 示例 here 对此进行了彻底解释。

如果您使用 PCRE 正则表达式,您可以利用 PCRE 的 (*SKIP)(*FAIL) 选项立即丢弃麻烦的匹配项,否则您必须在捕获组中捕获它们,然后您可以检查并丢弃整个匹配项是捕获-group 不为空。

这将是Regex101 demo 的 PCRE 方式

(?:(['"])(?:(?!\1|\\).|\\.)*\1|\/\/[^\n]*(?:\n|$)|\/\*(?:[^*]|\*(?!\/))*\*\/)(*SKIP)(*FAIL)|\^

如果您需要根据捕获组手动丢弃匹配项,请执行以下操作:

((['"])(?:(?!\2|\\).|\\.)*\2|\/\/[^\n]*(?:\n|$)|\/\*(?:[^*]|\*(?!\/))*\*\/)|\^

另请参阅Debuggex Demo,其中您要匹配的^ 是黄色的,表示它们不在捕获组中。所有其他匹配项都有一个捕获组,并在 Debuggex 视觉对象中以较暗的方式突出显示。

注意:我添加了对/*...*/ 和// cmets 的支持,但是这些都没有考虑到PHP 中的Heredoc/nowdoc 字符串,不知道这对你是否重要,你可以将其添加为相当简单的另一个替代匹配,应该是 (*SKIP)(*FAIL)ed 或捕获并丢弃。

【讨论】:

    【解决方案3】:

    只需将 awk 与字段和简单的正则表达式一起使用,而不是将 grep 与复杂的正则表达式一起使用,例如使用到目前为止在此线程中建议的所有示例输入:

    $ cat file
    'asdfasdf'; 'asdfasd'^'asdflkj';                YES
    ['asdf', '^', 'asdf'];                          NO
    ''o'^'o''                                       NO
    'asdf1524-sdfaA'^'sdfa322='                     YES
    'sdfa22_'^$myvar                                YES
    $myvar^'asAf34%'                                YES
    ['+','*','^','%']                               NO
    '^'=>2                                          NO
    'asdfa5A_sdf'; 'asd5A_fasd'^'asd5A_flkj';       YES
    'asdfa5A_'^$var1;                               YES
    $var2^'asdfa5A_';                               YES
    'asdf', '^', 'asdf';                            NO
    '+', '-', '*', '/', '^', '_');                  NO
    '+'=>0,'-'=>0,'*'=>0,'/'=>0,'^'=>1);            NO
    '+'=>0,'-'=>0,'*'=>1,'/'=>1,'_'=>1,'^'=>2);     NO
    '+', '-', '*', '/', '^'))) {                    NO
    
    $ awk -F"'" '{for (i=1;i<=NF;i+=2) if ($i ~ /\^/) {print; next}}' file
    'asdfasdf'; 'asdfasd'^'asdflkj';                YES
    'asdf1524-sdfaA'^'sdfa322='                     YES
    'sdfa22_'^$myvar                                YES
    $myvar^'asAf34%'                                YES
    'asdfa5A_sdf'; 'asd5A_fasd'^'asd5A_flkj';       YES
    'asdfa5A_'^$var1;                               YES
    $var2^'asdfa5A_';                               YES
    

    上述方法通过将每个' 的每一行拆分为一系列字段,因此奇数字段在引号对之外,而偶数字段在引号对内(例如out'in'out'in'out),然后你就拥有在奇数字段中查找^。

    如果可能的话,这需要更多的工作来处理字符串中的换行符和/或转义引号,但到那时你真的应该查看语言解析器而不是 shell 脚本。

    【讨论】:

      【解决方案4】:

      我需要在 grep 中工作,所以 pcre 不能正常工作(即使使用 pgrep)。 我最终使用了一个非常丑陋且并非总是有效的正则表达式:

      ^[^']*((('[^']*){1}|('[^']*){3}|('[^']*){5}|('[^']*){7}|('[^']*){9}|('[^']*){11})[^']+'\^.+|(('[^']*){0}|('[^']*){2}|('[^']*){4}|('[^']*){6}|('[^']*){8}|('[^']*){10})[^']+\^'.+)
      

      这适用于在运算符之前声明的最多 5 个字符串,并最终比较 [^']+\^'.+ 或 [^']+'\^.+。我知道,我知道......但这是我发现让它工作的唯一方法,当然只适用于单引号字符串。 它与这个示例文件完美配合:

      'asdfa5A_sdf'; 'asd5A_fasd'^'asd5A_flkj';
      'asdfa5A_'^$var1;
      $var2^'asdfa5A_';
      'asdf', '^', 'asdf';
      '+', '-', '*', '/', '^', '_');
      '+'=>0,'-'=>0,'*'=>0,'/'=>0,'^'=>1); 
      '+'=>0,'-'=>0,'*'=>1,'/'=>1,'_'=>1,'^'=>2); 
      '+', '-', '*', '/', '^'))) {
      

      欢迎提供更好的解决方案 :)。 感谢所有帮助我的人,特别是@npinti,他花了很多时间检查这个!

      【讨论】:

      • 为什么需要它在 grep 中工作?所有具有 grep 的平台也具有 awk,并且该解决方案在 awk 中清晰、简单且健壮,并且适用于任意数量的字符串(请参阅 stackoverflow.com/a/30326792/1745001)。
      猜你喜欢
      • 2021-08-14
      • 2014-05-06
      • 2012-06-05
      • 2013-12-25
      • 1970-01-01
      相关资源
      最近更新 更多