1

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

例子:

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

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

5 回答 5

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{,}
于 2012-09-22T06:13:41.307 回答
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/在 HS 的开头添加一个十六进制代码01(这是一个用于匹配目的的虚构换行符。
  • /^\(\x01[^\x01]\+\)\(\1\)\+$/{x;D}对于那些相同的行,即没有例外,用 PS 切换 HS 并删除这些行并开始下一次迭代。
  • s/.//;s/\x01/\n/gp;x;D'那些确实有异常的行,删除01添加到前面的添加的十六进制代码,用换行符替换所有其他此类代码并打印这些行。然后用 PS 切换 HS 并删除到第一个换行符并开始下一次迭代。
于 2012-09-22T11:35:54.950 回答
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 脚本中,然后执行它

于 2012-09-24T10:48:21.537 回答
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 ;-)

于 2012-09-21T17:03:46.720 回答
-1
KEY_STRINGS="`sort file | uniq | awk '{print$1}' | uniq -d`" 
awk -vkeys="$KEY_STRINGS" '{if(keys~/$1/)print$0}' file

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

于 2012-09-21T17:35:53.567 回答