我有一个 ASCII 文件 (Report.dat),其中包含以下几行:
a ./L1/file2.txt
c ./L1/file1.txt
b ./L2/file1.txt
a ./L2/file2.txt
我需要只获取第一列唯一的行,如下所示:
c ./L1/file1.txt
b ./L2/file1.txt
如何使用 AWK、sort 或 uniq 命令来做到这一点?
答案1
这是获得独特“标签”的方法:
$ awk '{ print $1 }' Report.dat | sort | uniq -u
b
c
^
通过在字符串前面添加,可以将它们转换为在行开头匹配的正则表达式:
$ awk '{ print $1 }' Report.dat | sort | uniq -u | sed 's/^/^/'
^b
^c
您可以将这些正则表达式应用于原始文件以获取相应的行:
$ awk '{ print $1 }' Report.dat | sort | uniq -u | sed 's/^/^/' | grep -f /dev/stdin Report.dat
c ./L1/file1.txt
b ./L2/file1.txt
我们grep -f /dev/stdin
告诉我们grep
采用来自的正则表达式sed
并使用它们来进行匹配Report.dat
。
或者,绕过该sed
步骤:
awk '{ print "^" $1 }' Report.dat | sort | uniq -u | grep -f /dev/stdin Report.dat
或者,也可以在以下位置完成所有操作awk
:
awk 'NR == FNR { c[$1]++; next } c[$1] == 1' Report.dat Report.dat
这会读取文件两次。第一次,它只是简单地计算每个“标签”出现的次数。第二次,它在打印该行之前测试当前行上的标签,看看其计数是否为 1。
请注意,无法解析文件两次。人们可以将完整的文件存储在内存中并在那里解析两次,但这很繁琐并且会出现问题在一般情况下当我们不知道要输入脚本的文件有多大时。