如何列出不包含两个不同字符串的所有文件

5
列出不包含两个不同字符串的所有文件。
我有一个目录,其中有许多按照一定模式命名的文件,例如file1.txt。
我可以列出所有不包含一个字符串的文件。
grep -l "String" file*

我该如何列出不包含我尝试的两个字符串的文件?
grep -l "string1|string2" file*

你是指要使用 -L 选项吗(-l 显示文件内容与给定正则表达式匹配的文件)? - chepner
如果一个文件只包含其中的一种字符串,应该打印出该文件的名称吗?另外,如果字符串1包含"f.o",并且文件中存在字符串"flo",这是否应视为匹配? - Ed Morton
是的,我正在尝试列出不包含任何字符串的文件。 - Paul33
@EdMorton 不仅应返回不包含该字符串的文件。 - Paul33
@Paul33 好的,我刚刚更新了我的答案。 - Ed Morton
2个回答

4
你需要在grep中使用参数e或者使用egrep。
使用egrep时:
egrep -L "string1|string2" file*

或者,只需转义“|”:grep -l "string1\|string2" - chepner
不错!我不知道那个。我一直在想 grep -l -e "string1|string2" - fedorqui
egrep 更容易输入,因为在使用分支运算符时使用 | 作为字面文本比使用它更为常见。 - chepner
@chepner已经评论了应该使用“-L”列出不包含模式的文件。 - sotapme
以上代码将把每个“字符串”视为正则表达式,因此“f.o”将匹配“foo”或“flo”等。我认为OP真正想要搜索的是字符串,而不是REs,因为他将它们命名为“string”。 - Ed Morton
显示剩余2条评论

1

假设你只想打印包含所有字符串的文件名,这是一个解决方案,适用于任意数量的字符串,并进行字符串比较,而不是正则表达式比较:

gawk -v RS='\0' -v strings="string1 string2" '
BEGIN{ numStrings = split(strings,stringsA) }
{
   matchCnt = 0
   for (stringNr=1; stringNr<=numStrings; stringNr++)
      if ( index($0,stringsA[stringNr]) )
         matchCnt++
}
matchCnt == numStrings { print FILENAME }
' file*

稍等,我刚刚注意到你想要打印不包含2个字符串的文件。那应该是:

gawk -v RS='\0' -v strings="string1 string2" '
BEGIN{ numStrings = split(strings,stringsA) }
{
   matchCnt = 0
   for (stringNr=1; stringNr<=numStrings; stringNr++)
      if ( index($0,stringsA[stringNr]) )
         matchCnt++
}
matchCnt == numStrings { matchesAll[FILENAME] }
END {
   for (fileNr=1; fileNr < ARGC; fileNr++) {
      file = ARGV[fileNr]
      if (! (file in matchesAll) )
         print file
   }
}
' file*

打印不包含任何字符串的文件名将是:

gawk -v RS='\0' -v strings="string1 string2" '
BEGIN{ numStrings = split(strings,stringsA) }
{
   for (stringNr=1; stringNr<=numStrings; stringNr++)
      if ( index($0,stringsA[stringNr]) )
         matchesOne[FILENAME]
}
END {
   for (fileNr=1; fileNr < ARGC; fileNr++) {
      file = ARGV[fileNr]
      if (! (file in matchesOne) )
         print file
   }
}
' file*

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接