我有一组文件,我需要遍历并找到所有在其他 2 个特定字符串之间没有特定字符串的文件。我怎样才能做到这一点?
我试过了,但没有用:
grep -lri "\(stringA\).*\(?<!stringB\).*\(stringC\)" ./*.sql
编辑:该文件可能具有如下结构:
StringA
StringB
StringA
StringC
我只想知道是否存在字符串 A 和字符串 C 之间没有字符串 C 的情况。
简短的回答如下:
grep "abc[^(?:def)]*ghi" ./testregex
这是基于像这样的 testregex 文件:
abcghiabc
abcdefghi
abcghi
输出将是:
$ grep "abc[^(?:def)]*ghi" ./testregex
abcghiabc
abcghi
映射到您的用例,我敢打赌这大致可以转化为:
grep -lri "stringA[^(?:stringB)]*stringC" ./*.sql
请注意,我已删除每个字符串之间的“.*”,因为这将匹配您尝试排除的字符串。
更新:原来的问题现在调用换行符,所以使用 grep 的 -z 标志:
-z
在行尾取消换行符,将其替换为空字符。也就是说,grep 知道行尾在哪里,但将输入视为一条大行。
因此:
grep -lriz "stringA[^(?:stringB)]*stringC" ./*.sql
当我第一次不得不自己使用这种方法时,我写了以下解释......
具体来说:我想匹配“任何字符,任意次数,非贪婪(因此请遵循后续显式模式),并且不匹配序列 />”。
最后一部分是我要分享的内容:“不匹配序列/>”。这是我第一次使用结合“任何字符”逻辑的字符序列。
我的目标字符串:
<img class="photo" src="http://d3gqasl9vmjfd8.cloudfront.net/49c7a10a-4a45-4530-9564-d058f70b9e5e.png" alt="Iron or Gold" />
我的第一次尝试:
<img.*?class="photo".*?src=".*?".*?/>
这在在线正则表达式测试器中有效,但在我的实际 Java 代码中由于某种原因失败了。通过反复试验,我发现替换每个“。?” 用“[^<>]?” 那是成功的。也就是说,代替“任何字符的非贪婪匹配”,我可以使用“除了 < 或 > 之外的任何字符的非贪婪匹配”。
但是,我不想使用它,因为我看到了包含这些字符的替代文本。在我的特殊情况下,我想使用字符序列“/>”作为排除序列——一旦遇到该序列,停止“任何字符”匹配。
这让我想到了我的教训:
第 1 部分:可以使用 (?:regex) 实现字符序列。也就是说,对字符序列正常使用 () 括号,但在前面加上“?:”,以防止序列被匹配为目标组。因此,"(?:/>)" 将匹配 "/>",而 "(?:/>)*" 将匹配 "/>/>/>/>"。
第 2 部分:此类字符序列可以以与单个字符相同的方式使用。即“[^(?:/>)]*?” 将匹配除序列“/>”之外的任何字符,任意次数,非贪婪。
差不多就是这样。搜索的关键词是“非捕获组”和“负前瞻|后视”,后一个功能比我到目前为止所了解的要深入得多,还有一些我还没有理解的标志。但最初的理解为我提供了我当前任务所需的工具,这是我一直想知道的一个功能 - 因此,我想我会分享基本介绍,以防你们中的任何人对折叠它感到好奇在你的工具集中。
您可以使用-L
选项grep
打印所有不匹配的文件并查找字符串的特定组合:
grep -Lri "\(stringA\).*\(stringB\).*\(stringC\)" ./*.sql
在玩弄了 DreadPirateShawn 提供的声明之后:
stringA[^(?:stringB)]*stringC
我发现它不是一个真正有效的正则表达式。该语句排除了给定集中的每个字符,而不是完整的字符串。于是我继续挖掘。
经过一些谷歌搜索和测试模式后,我想出了以下语句,这似乎符合我的需要:
stringA\s*\t*(?:(?!stringB).)*\s*\t*stringC
此模式匹配除2 个指定字符串之间提供的字符串之外的任何文本。它还考虑了空白字符。
还有更多的测试要做,但似乎这种模式完全符合我的要求
更新:这是该声明的最终版本,似乎对我有用:
grep -lriz "(set feedback on){0,}[ \t]*(?:(?!set feedback off).)*[ \t]*select sysdate from dual" ./*.sql