grep / awk - 基于多列丢弃行

时间:2012-09-21 16:26:14

标签: bash awk grep

我想根据多列中的匹配来丢弃行。对于第1列中的所有匹配事件,请检查相应的列2.仅当所有第2列条目相同时,才丢弃所有行。如果第2列中的一个条目不同,则保留所有行。

示例:

丢弃前3行,因为Bob的每个第2列条目都相同。但是,保留剩余的4行,因为第2列中至少有一个条目因Jan而异:

Bob Blue
Bob Blue
Bob Blue
Jan Red
Jan Red
Jan Green
Jan Red

5 个答案:

答案 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

我相信这个脚本会更容易理解。