3

我有一组文件,我需要遍历并找到所有在其他 2 个特定字符串之间没有特定字符串的文件。我怎样才能做到这一点?

我试过了,但没有用:

grep -lri "\(stringA\).*\(?<!stringB\).*\(stringC\)" ./*.sql

编辑:该文件可能具有如下结构:

StringA
StringB
StringA
StringC

我只想知道是否存在字符串 A 和字符串 C 之间没有字符串 C 的情况。

4

3 回答 3

2

简短的回答如下:

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 部分:此类字符序列可以以与单个字符相同的方式使用。即“[^(?:/>)]*?” 将匹配除序列“/>”之外的任何字符,任意次数,非贪婪。

差不多就是这样。搜索的关键词是“非捕获组”和“负前瞻|后视”,后一个功能比我到目前为止所了解的要深入得多,还有一些我还没有理解的标志。但最初的理解为我提供了我当前任务所需的工具,这是我一直想知道的一个功能 - 因此,我想我会分享基本介绍,以防你们中的任何人对折叠它感到好奇在你的工具集中。

于 2013-02-28T16:28:13.403 回答
2

您可以使用-L选项grep打印所有不匹配的文件并查找字符串的特定组合:

grep -Lri "\(stringA\).*\(stringB\).*\(stringC\)" ./*.sql
于 2013-02-28T16:31:44.247 回答
0

在玩弄了 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
于 2013-03-05T15:31:28.363 回答