我有一个包含2列的文件,如下所示:
apple pear
banana pizza
spoon fork
pizza plate
sausage egg
如果一个单词出现在多行中,我想删除重复出现的单词的所有行,如您所见,“比萨饼”出现了两次,因此应删除2行,以下是必需的输出:
apple pear
spoon fork
sausage egg
我知道要使用:
awk '!seen[$1]++'
但是,这仅在字符串出现在一列中时才删除行,我需要一条命令来检查两列。 我该如何实现?
答案 0 :(得分:5)
通过使用grep
和uniq -d
,可以分多个步骤解决问题。
首先,使用grep -Eo '[^ ]+'
之类的单词生成所有单词的列表。然后过滤该列表,以便仅保留重复的单词。可以使用… | sort | uniq -d
进行过滤。最后,从先前使用grep -Fwvf listFile inputFile
生成的列表中打印所有不包含任何单词的行。
在bash
中,所有这些步骤都可以在一个命令中运行。在这里,我们将使用变量$in
使其易于适应。
in="path/to/your/input/file"
grep -Fwvf <(grep -Eo '[^ ]+' "$in" | sort | uniq -d) "$in"
答案 1 :(得分:2)
使用awk,您可以跟踪许多事情。不仅您看到了一个单词,而且看到了单词的哪一行。我们跟踪几个数组。
record
:跟踪我们解析的每一行seen
:跟踪各个单词以及在其上看到的第一个记录编号这给我们:
awk '{ record[NR]=$0 }
{ for(i=1;i<=NF;++i) {
if ($i in seen) { delete record[NR]; delete record[seen[$i]] }
else { seen[$i]=NR }
}
}
END { for(i=1;i<=NR;++i) if (i in record) print record[i] }' file
这是如何工作的?
record[NR]=$0
:将记录$0
存储在以记录号record
索引的数组NR
中
record
中删除原始记录以及当前记录。如果找不到,请将单词和当前记录号存储在数组seen
中。record
的索引,则打印该记录。答案 2 :(得分:2)
$ awk '
NR==FNR {
for (i=1; i<=NF;i++) {
if ( firstNr[$i] ) {
multi[NR]
multi[firstNr[$i]]
}
else {
firstNr[$i] = NR
}
}
next
}
!(FNR in multi)
' file file
apple pear
spoon fork
sausage egg
或者,如果您愿意:
$ awk '
NR==FNR {
for (i=1; i<=NF;i++) {
cnt[$i]++
}
next
}
{
for (i=1; i<=NF;i++) {
if ( cnt[$i] > 1 ) {
next
}
}
print
}
' file file
apple pear
spoon fork
sausage egg
答案 3 :(得分:0)
这适用于您的示例:
#!/usr/bin/env sh
filename='x.txt'
for dupe in $(xargs -n1 -a "${filename}" | sort | uniq -d); do
sed -i.bak -e "/\\<${dupe}\\>/d" "${filename}"
done
它会建立一个单词列表,该单词列表在文件中出现多次:
xargs -n1 -a "${filename}"
输出所有单词的列表| sort
对列表进行排序| uniq -d
仅输出连续出现多次的单词然后使用sed
选择和删除所有包含重复单词的行。
答案 4 :(得分:0)
这可能对您有用(GNU grep,sort,uniq,sed):
///<reference ...
或玩具GNU sed解决方案:
sed 's/ /\n/g' file | sort |uniq -d | grep -vFf - file