匹配字符串运算符的正则表达式

Regular expression to match string operator

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

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

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

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

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

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

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

但是 它不应该匹配:

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

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

提前致谢!

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

你想做的是明确地捕捉可能包含^字符串't 想要匹配然后丢弃该字符串。这个解释的很透彻here and with a JavaScript example here.

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

这将是 Regex101 demo

的 PCRE 方式
(?:(['"])(?:(?!|\).|\.)*|\/\/[^\n]*(?:\n|$)|\/\*(?:[^*]|\*(?!\/))*\*\/)(*SKIP)(*FAIL)|\^

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

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

另见 Debuggex Demo,其中 ^ 的你 do 想要匹配是黄色的,表示他们不在捕获组中。所有其他匹配项都有一个捕获组,并在 Debuggex 视觉对象中以较暗的颜色突出显示。

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

只需将 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 ) 然后您只需在奇数字段中查找 ^

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

我需要在 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,他花了很多时间检查这个!