awk::如何在两个文件中找到匹配的单词

  • 本文关键字:单词 文件 awk 两个 awk
  • 更新时间 :
  • 英文 :


StackOverflow上的一些好心人帮我找到了使用awk的两个文件中的共同行:

awk 'NR==FNR{a[tolower($0)]; next} tolower($0) in a' 1.txt 2.txt

但是如何在两个单词排成一行的文件中找到常用词呢?

例如,假设我有1.txt和这些单词:

apple
orange
butter
flower

然后2.txt加上这些字:

dog cat Butter tower

如何返回butterButter?

我只是想找一下常用词。

这个grep应该可以完成这项工作:

grep -oiwFf 1.txt 2.txt
Butter

或者这个简单的gnu awk也可以:

awk -v RS='[[:space:]]+' 'NR==FNR {w[tolower($1)]; next} tolower($1) in w' 1.txt 2.txt
Butter

给定:

$ cat file1
apple 
orange 
butter
flower
$ cat file2
dog cat Butter tower

我会这样写:

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

注意,在FNR==NR的情况下,有一个逐字段循环,用于处理每行可能有多个单词的文件。如果您知道情况并非如此,则可以简化为:

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

如果这在Windows上不起作用,可能是rn行结尾的问题。如果awk使用RS=[n]值,则r留在一行末尾的所有单词上;butterr不匹配butter.

试题:

awk -v RS='[ rnt]' 'FNR==NR{words[tolower($0)]; next}
tolower($0) in words' file1 file2 

链接中对WSL注释的注释:

在DOS上处理Unix文件的方法有很多。

创建file1与DOS行结束如下:

$ printf 'applernorangernbutterrnflowerrn' >file1 

现在你可以测试/看到文件有那些以cat -v结尾的行:

$ cat -v file1
apple^M
orange^M
butter^M
flower^M

您还可以删除以sed,perl,awk等结尾的行。下面是awk从文件中删除r:

$ cat -v <(awk 1 RS='rn' ORS='n' file1)
apple
orange
butter
flower

Asedandperl:

$ cat -v <(sed 's/r$//' file1)
#same

$ cat -v <(perl -0777 -lpe 's/rn/n/g' file1)

等。然后对awk-on-windows:

使用相同的结构
awk 'your_awk_program' <(awk 1 RS='rn' ORS='n' file1) <(awk 1 RS='rn' ORS='n' file2)

缺点:虽然每个输入都被视为不同的逻辑文件,因此FNR==NRawk测试仍然有效,但awk特殊变量FILENAME在该过程中丢失了。如果您希望将FILENAME与实际文件相关联,则需要在提供给awk之前对文件进行预处理,或者在awk脚本中处理r

您需要遍历每行(2.txt)的每个字段并检查:

awk 'NR==FNR{a[tolower($0)];next}{for(i=1;i<=NF;i++){if(tolower($i) in a){print $i}}}' 
1.txt 2.txt
在awk中执行此操作的另一种方法是在处理第二个文件时在输入记录分隔符中添加空白:
awk 'NR==FNR{a[tolower($0)];next} tolower($0) in a' 1.txt  RS="[n ]" 2.txt

最新更新