我想根据多列中的匹配来丢弃行。对于第1列中的所有匹配事件,请检查相应的列2.仅当所有第2列条目相同时,才丢弃所有行。如果第2列中的一个条目不同,则保留所有行。
示例:
丢弃前3行,因为Bob的每个第2列条目都相同。但是,保留剩余的4行,因为第2列中至少有一个条目因Jan而异:
Bob Blue
Bob Blue
Bob Blue
Jan Red
Jan Red
Jan Green
Jan Red
答案 0 :(得分:4)
这是使用GNU awk
的一种方式。像:
awk -f script.awk file.txt{,}
script.awk
的内容:
FNR==NR {
array[$0]++
next
}
{
counter = 0
for (i in array) {
split(i, holder, FS)
if (holder[1] == $1) {
counter++
}
}
if (counter >= 2) {
print
}
}
结果:
Jan Red
Jan Red
Jan Green
Jan Red
或者,这是单行:
awk 'FNR==NR { array[$0]++; next } { counter = 0; for (i in array) { split(i, holder, FS); if (holder[1] == $1) counter++ } if (counter >= 2) print } ' file.txt{,}
答案 1 :(得分:3)
这可能对你有用(虽然它是GNU sed):
sed ':a;$!N;/^\(\S*\s\).*\n\1/{s/\n/\x01/;ba};h;x;s/\n.*//;s/^/\x01/;/^\(\x01[^\x01]\+\)\(\1\)\+$/{x;D};s/.//;s/\x01/\n/gp;x;D' file
说明:
:a
循环标记$!N
除非是最后一行,否则在模式空间(PS)附加换行符和下一行/^\S*\s).*\n\1/{s/\n/\x01/;ba}
将以同一个键开头的所有行组成一行,用十六进制代码替换换行符01
h
将当前PS存储在保留空间(HS)x
用HS切换PS s/\n.*//
删除附加的最后一行(这不匹配)s/^/\x01/
将十六进制代码01
添加到HS的开头(这是用于匹配目的的虚构换行符。/^\(\x01[^\x01]\+\)\(\1\)\+$/{x;D}
对于那些完全相同但没有例外的行,用HS切换HS并删除这些行并开始下一次迭代。s/.//;s/\x01/\n/gp;x;D'
那些有异常的行,删除添加到前面的添加的十六进制代码01
,用换行符替换所有其他此类代码并打印这些代码行。然后用PS切换HS并删除第一个换行符并开始下一次迭代。答案 2 :(得分:0)
如果您的输入位于名为“test.txt”的文本文件中,则可以使其运行:
cat test.txt | grep ^`cat test.txt | sort -u | awk 'BEGIN{split("", aux, "");ok="";} {if ($1 in aux){if (length(ok) > 0){ok=ok"\|"$1;}else{ok=$1;}}aux[$1]="";} END{print ok;}' -`
您可以逐步执行以了解命令,或者您可以问我(AWK部分有点复杂)。
这样,输出为:
Jan Red
Jan Red
Jan Green
Jan Red
编辑:我忘了在“|”中添加反斜杠grep的OR; - )
答案 3 :(得分:0)
三个简单的步骤:
sort -u temp | nawk '{a[$1]++}END{for(i in a)print i,a[i]}' > temp_file
nawk 'FNR==NR{a[$1]=$2;next}{if(($1 in a) && a[$1]>1)print $0}' temp_file your_file
rm -rf tempfile
您可以将这些步骤合并到shell脚本中,然后执行它
答案 4 :(得分:-1)
KEY_STRINGS="`sort file | uniq | awk '{print$1}' | uniq -d`"
awk -vkeys="$KEY_STRINGS" '{if(keys~/$1/)print$0}' file
我相信这个脚本会更容易理解。