【问题标题】:Compare every second line, print line after but delete duplicates每隔两行比较一次,在之后打印行但删除重复项
【发布时间】:2011-12-02 07:06:12
【问题描述】:

我有一个格式如下的文件:

id-of-item

description of item

id-of-item

description of item

id-of-item

description of item

id-of-item

description of item

id-of-item

description of item

(每行之间只有一行,这里只是大空格)

我需要比较项目的描述,如果它们匹配,则删除该描述但保留 id(我需要制作一个将 id 作为组引用的表)

我不知道该怎么做,我尝试了几个 awk 与 NR%2 和 uniq 等,但显然都只匹配一个而不匹配另一个 =/

【问题讨论】:

  • 您能否包括实际的输入格式而不是下面的描述,包括预期的输出?
  • 我不太明白“每个之间只有一行”。空行是记录分隔符,描述可能跨越多行?空行没有意义,奇数行有ID,偶数行有单行描述?

标签: shell sed terminal awk grep


【解决方案1】:

这可能很接近。 awk 的规则是, 将任何你想杀死重复的东西放入数组的索引中:

BEGIN {title = ""}
NF == 0 { print; next;}
title == "" {
    title = $0;
    print; next;
}
{
    if (value[$0] == "" ) print;
    value[$0] = $0;
    title = ""
}

感受关联数组的威力。

【讨论】:

  • 实际上看起来非常完美,非常感谢 =] 印刷品给我留下了深刻的印象;下一个;我不知道你能做到这一点=]
【解决方案2】:

我将做两个简化的假设:

  1. 说明只有一行。
  2. 您可以识别未出现在描述或 ID 中的字符。我会为这个角色使用一个制表符。

这两个假设都不是很强,所以如果需要,调整以下内容应该不难。

有了这些假设,我将使用printf "1\n\nitem 1\n\n2\n\nitem 2\n\n3\n\nitem 2\n\n4\n\nitem 1\n" 生成样本数据。它看起来像这样:

1

item 1

2

item 2

3

item 2

4

item 1

为了处理这些数据,我将:

  1. 去掉空行
  2. 连接连续的行,用制表符分隔 ID 和描述
  3. 按描述字段对新行进行排序
  4. 将已排序的行格式化为表格

这是一个可以做到这一点的管道:

grep -v '^[[:space:]]*$' |        
  awk 'NR%2 { printf("%s\t", $0) } !(NR%2)' | 
    sort -k2 | 
      awk -F"\t" 'desc != $2 { printf("-----\n%s\n", $2); desc = $2} { print $1 }'

通过它传递样本数据,你得到

-----
item 1
1
4
-----
item 2
2
3

【讨论】:

    【解决方案3】:

    这可能对你有帮助(?):

    # cat input.txt
    id-of-item0
    id-of-item0 description of item0
    id-of-item1
    id-of-item1 description of item1
    id-of-item0
    id-of-item0 description of item0
    id-of-item3
    id-of-item3 description of item3
    id-of-item4
    id-of-item4 description of item4
    # sed 'N;s/\n/!!!/' input.txt | sort -u | sed 's/!!!/\n/'
    id-of-item0
    id-of-item0 description of item0
    id-of-item1
    id-of-item1 description of item1
    id-of-item3
    id-of-item3 description of item3
    id-of-item4
    id-of-item4 description of item4
    

    如果要删除描述:

    # sed 'N;s/\n/!!!/' input.txt | sort -u | sed 's/!!!.*//'
    id-of-item0
    id-of-item1
    id-of-item3
    id-of-item4
    

    解释:

    一次读取input.txt 2 行,用分隔符替换换行符\n(这里是!!!)。排序并删除重复项。将分隔符 !!! 替换为换行符 \n。或者完全删除描述。

    编辑:

    这可能对你有用(?):

    sed '/^$/d' input_file |   # remove empty lines
    sed -n 'h;n;G;s/\n/\t/p' | # join id with description and swap tab separating
    sort |                     # sort descriptions
    sed ':a;N;s/^\(\([^\t]*\)\t[^\n]*\)\n\2/\1/;ta;P;D' | # build index tab separated
    sed 's/\t/\n/g'            # translate tabs to newlines
    

    【讨论】:

    • 如果我错了,我就错了!但是,那些更聪明的人的评论可能会将我推向正确的方向。
    【解决方案4】:

    这行得通吗?

    awk 'NF' file | sed '{N;s/\n/:/g}' | 
    awk -F":" -v OFS="\n\n" -v ORS="\n\n"  '{b[$2]++} {if (b[$2]>1) print $1; else print $1,$2}'
    

    您的文件:

    [jaypal:~/Temp] cat file
    id-of-item31
    
    description of item4 <--- Duplicate description
    
    id-of-item22
    
    description of item4 <--- Duplicate description
    
    id-of-item34
    
    description of item1 <--- Duplicate description
    
    id-of-item21
    
    description of item3
    
    id-of-item11
    
    description of item1 <--- Duplicate description
    

    执行:

    [jaypal:~/Temp] awk 'NF' file | sed '{N;s/\n/:/g}' | 
    awk -F":" -v OFS="\n\n" -v ORS="\n\n"  '{b[$2]++} {if (b[$2]>1) print $1; else print $1,$2}'
    
    id-of-item31
    
    description of item4
    
    id-of-item22
    
    id-of-item34
    
    description of item1
    
    id-of-item21
    
    description of item3
    
    id-of-item11
    

    【讨论】:

    • 哦,我的错!我已将主文件转换为临时文件以进行测试。我会更新上面的答案。
    猜你喜欢
    • 1970-01-01
    • 2020-11-10
    • 2021-12-09
    • 2019-03-19
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-10
    相关资源
    最近更新 更多