从列表中搜索字符串的文件

时间:2014-06-04 15:02:20

标签: bash grep io-redirection

我有一个文本文件目录,每个文件都包含一行"功能号码:"接着是一些数字。我还有另一个文本文件,其中包含我想要搜索它们的顺序的文件名列表。我尝试了以下bash命令:

while read LINE; do
  grep -i 'feature number' $LINE > outputFile.txt
done < ../listOfFiles.txt

但从未收到任何输出。

grep -f ../listOfFiles.txt p*.txt也没有返回任何内容,但

read LINE < ../listOfFiles.txt; echo $LINE确实如此 grep -i 'feature number' oneOfTheFiles.txt确实如此。

该命令的哪一部分无效,我该如何解决?

2 个答案:

答案 0 :(得分:3)

提供答案,总结评论意见中的所有有用提示:

@fedorqui 指出在循环中使用> ,在每次迭代中覆盖输出文件循环,因此实际上只在输出文件中捕获 last 迭代的输出。

立即修复是使用>> ,而附加到现有输出文件(或创建它,如果它不存在)。

while read -r LINE; do
  grep -i 'feature number' "$LINE" >> outputFile.txt
done < ../listOfFiles.txt

请注意,我还使代码段更加强大:

  • read -r确保在不解释\字符的情况下读取输入行。 - 但是,从每一行修剪前导和尾随空格。
  • "$LINE"现在是双引号,以防止它被shell扩展;例如,如果变量值包含空格,则这是必要的。

但是, >>会附加到任何预先存在的 outputFile.txt ,因此,如果您多次运行该代码段,则该文件会保留越来越大。


为防止这种情况发生,您可以事先明确截断(: >outputFile.txt)或删除(rm -f outputFile.txt)输出文件,或者最好利用@konsoelbox推荐的简化< /强>:

while read -r LINE; do
  grep -i 'feature number' "$LINE"
done < ../listOfFiles.txt > outputFile.txt

通过将输出重定向 - > - 置于while循环的 end 所有次迭代的输出为作为一个整体捕获,同时替换任何已存在的文件


最后, @tripleee 建议使用xargs代替while循环更彻底的简化:

xargs grep -h -i 'feature number' < ../listOfFiles.txt > outputFile.txt

这将(通常)导致 单个调用grep所有输入行作为文件名参数传递。< / p>

除了缩短写作时,这种方法效率更高 请注意使用grep -h,它会禁止匹配前缀与原始文件的名称。

警告:只要../listOfFiles.txt中的文件名没有嵌入空格,此就可以正常运行,因为每个此类文件名都会被拆分为多个参数。

正确处理包含空格的文件名

  • 如果您有 GNU xargs请使用-d'\n' 以确保在传递给{时将每一行视为自己的参数{1}}:

    grep
  • 如果您只有 POSIX兼容 xargs -d'\n' grep -h -i 'feature number' < ../listOfFiles.txt > outputFile.txt 使用xargs ,但这意味着每个输入行都会为-I调用

    grep
  • 最后,如果你有一个支持xargs -I % grep -i 'feature number' % < ../listOfFiles.txt > outputFile.txt xargs版本来处理NUL分隔的输入(例如,GNU -0,FreeBSD( OSX)xargs),您可以使用以下技巧:

    xargs

请注意,基于xargs -0 grep -h -i 'feature number' \ < <(tr '\n' '\0' < ../listOfFiles.txt) > outputFile.txt 的方法通常是最强大的方法,因为它甚至支持具有嵌入式-0字符的参数。但是NUL分离的输入并不总是随时可用,因为需要\n技巧演示。

答案 1 :(得分:-1)

grep命令应该是这样的:

grep -inr&#34;搜索字符串&#34;