给定:
$ 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 上不起作用,则可能是 \r\n 行结尾的问题。如果awk 使用RS=[\n] 值,则\r 将留在行尾的所有单词上; butter\r 与 butter 不匹配。
试试:
awk -v RS='[ \r\n\t]' 'FNR==NR{words[tolower($0)]; next}
tolower($0) in words' file1 file2
在链接中对您的 WSL cmets 的评论:
您在 DOS 上处理 Unix 文件的解决方法有很多。
以这种方式创建带有 DOS 行结尾的 file1:
$ printf 'apple\r\norange\r\nbutter\r\nflower\r\n' >file1
现在您可以测试/查看文件以cat -v 结尾的那些行:
$ cat -v file1
apple^M
orange^M
butter^M
flower^M
您还可以删除带有sed、perl、awk 等的行结尾。这是从文件中删除\r 的awk:
$ cat -v <(awk 1 RS='\r\n' ORS='\n' file1)
apple
orange
butter
flower
sed 和 perl:
$ cat -v <(sed 's/\r$//' file1)
#same
或
$ cat -v <(perl -0777 -lpe 's/\r\n/\n/g' file1)
等等。然后在 awk-on-windows 中使用相同的构造:
awk 'your_awk_program' <(awk 1 RS='\r\n' ORS='\n' file1) <(awk 1 RS='\r\n' ORS='\n' file2)
缺点:虽然每个输入都被视为不同的逻辑文件,所以 FNR==NR awk 测试仍然有效,但 awk 特殊变量 FILENAME 在此过程中丢失。如果您想保持FILENAME 与实际文件相关联,您需要在馈送到 awk 之前对文件进行预处理,或者在 awk 脚本中处理 \r。