【问题标题】:How to print specific duplicate line based on fields number如何根据字段编号打印特定的重复行
【发布时间】:2012-02-15 22:55:28
【问题描述】:

我只需要打印具有相同第一个字段的各种连续行中的一个,并且该行必须是具有“最后一个字段中的更多字段”的行。这意味着最后一个字段是一组单词,我需要在最后一个字段中打印包含更多元素的行。如果最后一个字段的最大元素数相同,则任何最大值都可以。

示例输入:

("aborrecimento",[Noun],[Masc],[Reg:Sing],[Bulk])
("aborrecimento",[Noun],[Masc],[Reg:Sing],[Device,Concrete,Count])
("aborrecimento",[Noun],[Masc],[Reg:Sing],[])
("adiamento",[Noun],[Masc],[Reg:Sing],[])
("adiamento",[Noun],[Masc],[Reg:Sing],[Count])
("adiamento",[Noun],[Masc],[Reg:Sing],[VerbNom])

示例输出:

("aborrecimento",[Noun],[Masc],[Reg:Sing],[Device,Concrete,Count])
("adiamento",[Noun],[Masc],[Reg:Sing],[VerbNom])

使用 awk 的解决方案会很好,但不需要一个衬垫。

【问题讨论】:

  • 试图提取我应该打印哪一行,然后打印该行本身,但无法猜测如何从各种候选者那里获取该行。

标签: awk duplicates


【解决方案1】:

生成索引文件

$ cat input.txt |
sed 's/,\[/|[/g' | 
awk -F'|' '
{if(!gensub(/[[\])]/, "", "g", $NF))n=0;else n=split($NF, a, /,/); print NR,$1,n}
' | 
sort -k2,2 -k3,3nr | 
awk '$2!=x{x=$2;print $1}' >idx.txt

索引文件内容

$ cat idx.txt
2
5

选择行

$ awk 'NR==FNR{idx[$0]; next}; (FNR in idx)' idx.txt input.txt
("aborrecimento",[Noun],[Masc],[Reg:Sing],[Device,Concrete,Count])
("adiamento",[Noun],[Masc],[Reg:Sing],[Count])

注意:input.txt中没有空格

【讨论】:

  • 它工作得非常完美。我有空格,但可以用它们代替下划线。你完全符合我的观点,我也试图生成那个 idx.txt,但不知道 gensub 函数,我需要更深入地研究 awk !非常感谢!
【解决方案2】:

使用[作为字段分隔符,然后在上分割最后一个字段,

awk -F '[[]' '
    {split($NF, f, /,/)}
    length(f) > max[$1] {line[$1] = $0; max[$1] = length(f)}
    END {for (l in line) print line[l]}
' filename

由于顺序很重要,因此更新:

awk -F '[[]' '
    {split($NF, f, /,/)}
    length(f) > max[$1] {line[$1] = $0; max[$1] = length(f); nr[$1] = NR}
    END {for (l in line) printf("%d\t%s\n", nr[$1], line[l])}
' filename |
sort -n |
cut -f 2-

【讨论】:

  • 非常好的解决方案,但它不尊重我需要的顺序(抱歉我没有指定)。对输出应用排序也不起作用,因为输入包含非 ascii 字符(“ab, áb, bb”变成“ab, bb, áb”)
【解决方案3】:

这样的事情可能会奏效:

awk 'BEGIN {FS="["} 
     Ff != gensub("^([^,]+).*","\\1","g",$0) { Ff = gensub("^([^,]+).*","\\1","g",$0) ; Lf = $NF ; if (length(Ml) > 0) { print Ml } }
     Ff == gensub("^([^,]+).*","\\1","g",$0) { if (length($NF) > length(Lf)) { Lf=$NF ; Ml=$0 } }    
     END {if (length(Ml) > 0) { print Ml } }' INPUTFILE

See here in action但是这不是您想要使用的解决方案,因为这更像是一种 hack。如果你的意思是你的最后一个字段比你最后一个元素的长度更长,那么它会让你失败。 (例如,上面的脚本很高兴地报告 [KABLAMMMMMMMMMMM!][A,B,C] 长。)

【讨论】:

  • 是的,最长的最后一个字段包含更多的分隔元素,而不是字符长度。
【解决方案4】:

这可能对你有用:

sort -r file | sort -t, -k1,1 -u

【讨论】:

    猜你喜欢
    • 2015-02-17
    • 1970-01-01
    • 2013-03-16
    • 2019-08-05
    • 1970-01-01
    • 2015-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多