如何在awk内部运行grep



假设我有一个文件input.txt,它有几列几行,第一列是键,还有一个目录dir,它有包含其中一些键的文件。我想找到dir中文件中包含这些关键字的所有行。一开始我试着运行命令

cat input.txt | awk '{print $1}' | xargs grep dir

这不起作用,因为它认为密钥是我的文件系统上的路径。接下来我尝试了类似的东西

cat input.txt | awk '{system("grep -rn dir $1")}'

但这也不起作用,最终我不得不承认,即使这样也不起的作用

cat input.txt | awk '{system("echo $1")}'

在我试图用逃离空白和$标志后,我来这里征求你的意见,有什么想法吗?

我当然可以做一些类似的事情

for x in `cat input.txt` ; do grep -rn $x dir ; done

这还不够好,因为它需要两个命令,但我只想要一个。这也说明了为什么xargs不起作用,该参数不是的最后一个参数

您不需要grepawk,也不需要cat来打开文件:

awk 'NR==FNR{keys[$1]; next} {for (key in keys) if ($0 ~ key) {print FILENAME, $0; next} }' input.txt dir/*

也不需要xargs、shell循环或其他任何东西——只需一个简单的awk命令即可完成所有操作。

如果input.txt不是一个文件,那么将上面的内容调整为:

real_input_generating_command |
awk 'NR==FNR{keys[$1]; next} {for (key in keys) if ($0 ~ key) {print FILENAME, $0; next} }' - dir/*

它所做的就是从第一个文件(或输入流)创建一个键数组,然后在dir目录中的每个文件中查找该数组中的每个键。

尝试以下

awk '{print $1}' input.txt | xargs -n 1 -I pattern grep -rn pattern dir

您应该做的第一件事就是对此进行研究。

下一步。。。你不需要在awk里面掷骰子。这完全是多余的。就像。。。往火鸡里塞。。火鸡。

Awk可以处理输入并像处理本身一样执行"grep",而无需启动grep命令。但你甚至不需要这么做。调整您的第一个示例:

awk '{print $1}' input.txt | xargs -n 1 -I % grep % dir

这使用xargs的-I选项将xargs输入放到它运行的命令行上的另一个位置。在FreeBSD或OSX中,您可以使用-J选项。

但我更喜欢你的for循环想法,转换为while循环:

while read key junk; do grep -rn "$key" dir ; done < input.txt

使用流程替换创建一个关键字"文件",您可以通过-f选项将其传递给grep

grep -f <(awk '{print $1}' input.txt) dir/*

这将在dir中的每个文件中搜索包含awk命令打印的关键字的行。它相当于

awk '{print $1}' input.txt > tmp.txt
grep -f tmp.txt dir/*

grep要求参数的顺序为:〔搜索内容〕〔搜索位置〕。您需要合并从awk接收的密钥,并使用\|regexp运算符将它们传递给grep。例如:

arturcz@szczaw:/tmp/s$ cat words.txt 
foo
bar
fubar
foobaz
arturcz@szczaw:/tmp/s$ grep 'foo|baz' words.txt 
foo
foobaz

最后,您将完成:

grep `commands|to|prepare|a|keywords|list` directory

如果您仍然想在awk中使用grep,请确保报价之外有$1、$2等。这个效果很好

cat file_having_query | awk '{system("grep " $1 " file_to_be_greped")}'

//注意grep之后和文件名之前的空格

最新更新