"while read LINE do" and grep problems

4

我有两个文件。

file1.txt:  
Afghans  
Africans  
Alaskans  
...  

其中file2.txt包含从网页上wget获取的输出结果,因此它是一个杂乱无章的大文件,但确实包含了第一个列表中的许多单词。

Bash脚本:

cat file1.txt | while read LINE; do grep $LINE file2.txt; done

这并没有像预期的那样工作。我想知道为什么,所以我在循环内部输出了$LINE变量并添加了一个sleep 1,这样我就可以看到发生了什么:

cat file1.txt | while read LINE; do echo $LINE; sleep 1; grep $LINE file2.txt; done

输出结果在终端上看起来应该是这样的:

阿富汗人
非洲人
阿拉斯加人
阿尔巴尼亚人
美国人
grep: Chinese: 没有那个文件或目录
: 没有那个文件或目录
阿拉伯人
阿拉伯人
阿拉伯人/印度人
: 没有那个文件或目录
阿根廷人
亚美尼亚人
亚洲人
印度裔亚洲人
: 没有那个文件或目录
file2.txt: Asian Naruto
...

所以你可以看到它最终找到了单词 "Asian"。但为什么会显示:

没有那个文件或目录


这里发生了奇怪的事情还是我漏了什么?

1
你只是在询问发生了什么吗?还是在寻求编写脚本的解决方案? - MJB
我肯定想知道为什么它不起作用,但我也愿意通过一个工作版本的示例来学习,明白吗? - Kevin
5个回答

5

关于什么

grep -f file1.txt file2.txt

3

@OP,首先按建议使用dos2unix。然后使用awk。

awk 'FNR==NR{a[$1];next}{ for(i=1;i<=NF;i++){ if($i in a) {print $i} } } '  file1 file2_wget

注意:在循环内使用while和grep不够高效,因为每次迭代都需要在file2上调用grep。
@OP,简单解释: 有关FNR和NR的含义,请参阅gawk manualFNR==NR{a[1];next} 表示将file1的内容存储到数组a中。当FNR不等于NR(即现在正在读取第二个文件)时,它将检查文件中的每个单词是否在数组a中。如果是,则打印出来。(for循环用于迭代每个单词)

能够工作真是太棒了。不过,我可以麻烦你(简要地)解释一下它的作用吗?我对 Awk 不是很了解,但我真的很想知道它是如何工作的。谢谢伙计! - Kevin
顺便说一下,为了你的利益,我简要地说一下,如果你想教我这个,我完全不反对... - Kevin

2

多使用引号,少使用cat

while IFS= read -r LINE; do 
  grep "$LINE" file2.txt
done < file1.txt

1
在这种情况下,grep 将会消耗所有为 read(也不是 file2.txt)准备的输入。 - Ignacio Vazquez-Abrams

1
尽管使用awk更快,但grep可以用更少的努力产生更多细节。因此,在执行dos2unix之后,请使用以下命令:grep -F -i -n -f <file_containing_pattern> <file_containing_data_blob>。您将获得所有匹配项+行号(不区分大小写)。最少这足以找到file_containing_pattern中的所有单词。
grep -F -f <file_containing_pattern> <file_containing_data_blob>

1

除了引用问题之外,您下载的文件还包含CRLF行尾,这会使read出现错误。在迭代文件之前,请使用dos2unix将file1.txt转换一下。


有趣。你已经为我提供了两个解决方案。谢谢。但我还是有点困惑。我刚刚创建了一个测试文件,其中包含file1.txt中的第一项之一。我使用相同的命令,带上"$LINE",但它在grep中找不到。有任何想法为什么吗? - Kevin
这个新文件使用什么行结尾? - Ignacio Vazquez-Abrams
抱歉,我误读了。应该是换行符,我使用vi编辑器进行了操作。这个回答解决了您的问题吗? - Kevin
好的,我希望你还没有对我感到厌烦 ;) 我在vim中使用了:set invlist,并发现它是用于行结尾的"$"。这是否意味着我需要设置IFS=$?也许你可以给我最后一点指引,我就能够解决这个问题了? - Kevin
vi 可以创建任何行结尾的文件。使用 dos2unix 确保文件使用 LF 行结尾。 - Ignacio Vazquez-Abrams

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