删除仅包含每个项目1的行

时间:2017-05-23 08:11:48

标签: shell awk

我有一个相当有趣的问题,我不确定如何处理。我的文件看起来像这样:

GROUP1, 1 Tall.hat, 1 Bow.tie, 1 Shiny.shoe, 
GROUP2, 1350 Red.apple, 1 Black.pencil, 1 Blue.pen, 1 Green.pen, 1 Little.tree, 
GROUP30, 2 Green.bow, 4 Big.tree, 
GROUP170, 1 Yellow.banana, 2 Green.apple, 1 Blue.skirt, 1 Purple.top, 1 Silver.shoe,
GROUP6, 2 Tall.hat, 2 Bow.tie, 2 Shiny.shoe, 
GROUP7, 20 Red.apple, 20 Black.pencil, 20 Blue.pen, 20 Green.pen, 20 Little.tree, 

每一行都包含一个包含项目的组,例如GROUP1包含1个Tall.hat,1个Bow.tie和1个Shiny.shoe。列以逗号分隔。我想删除每个项目只包含1个的行(或GROUP)。

期望的输出:

GROUP2, 1350 Red.apple, 1 Black.pencil, 1 Blue.pen, 1 Green.pen, 1 Little.tree, 
GROUP30, 2 Green.bow, 4 Big.tree, 
GROUP170, 1 Yellow.banana, 2 Green.apple, 1 Blue.skirt, 1 Purple.top, 1 Silver.shoe,
GROUP6, 2 Tall.hat, 2 Bow.tie, 2 Shiny.shoe, 
GROUP7, 20 Red.apple, 20 Black.pencil, 20 Blue.pen, 20 Green.pen, 20 Little.tree, 

因此GROUP1已被删除,因为它只包含每个项目中的1个。所有其他组至少有一个项目有两个或更多副本。

到目前为止的想法:

我需要忽略(但保留)column1,因为它包含组号。所以从awk -F "," 'NF>1'开始。然后对于每一行,循环遍历所有列并记录找到的所有可能数字。例如,GROUP1 = 1; GROUP2 = 1350或1; GROUP30 = 2或4,GROUP170 = 1或2.如果找到唯一的唯一编号是1,则删除该行。

不确定如何实际实现这一点......任何想法都会很棒!

3 个答案:

答案 0 :(得分:1)

这是使用awk的解决方案:

awk -F', *' '{ 
    split("", counts) # empty the counts array at the start of each line
    for (i = 2; i <= NF; ++i) { # loop through fields, starting from 2nd
        split($i, a, /[. ]/) # split each field into parts
        counts[a[3]] += a[1] # accumulate count for each type
        if (counts[a[3]] > 1) { print; next } # print and skip to next line
    }
}' file

-F', *'将字段分隔符设置为逗号,后跟任意数量的空格。这使得事情变得容易一些,因为额外的空间被消耗掉,并且不会在以后的每个字段$2$3中形成一部分。

counts将包含“apple”,“pencil”,“pen”等键。对于每个键,值为总出现次数。

如果你为“Blue.pen”和“Green.pen”保留单独的计数,那么只需分成一个空格split($i, a, / /),而不是空格和点。现在,每个字段只会分为两部分,因此请在后续行中将a[3]替换为a[2]

split使用空字符串清除counts数组是非GNU版本的awk的解决方法,可以用delete(counts)替换。

答案 1 :(得分:0)

awk 解决方案:

awk -F", *" '{split($2,a," "); n=a[1]; for(i=3;i<NF;i++){ split($i,a," "); 
            if (a[1]!=n) { print; next} else {n=a[1]}} if(n!=1){ print } }' file

输出:

GROUP2, 1350 Red.apple, 1 Black.pencil, 1 Blue.pen, 1 Green.pen, 1 Little.tree, 
GROUP30, 2 Green.bow, 4 Big.tree, 
GROUP170, 1 Yellow.banana, 2 Green.apple, 1 Blue.skirt, 1 Purple.top, 1 Silver.shoe,
GROUP6, 2 Tall.hat, 2 Bow.tie, 2 Shiny.shoe, 
GROUP7, 20 Red.apple, 20 Black.pencil, 20 Blue.pen, 20 Green.pen, 20 Little.tree,

详细

  • split($2,a," ") - 按空格拆分项目,以便a[1]填充数字,a[2]包含项目名称

  • n=a[1] - 捕获每组中第一个项目的编号

  • for(i=3;i<NF;i++) - 迭代剩余的项目

  • if (a[1]!=n) { print; next} - 在第一种情况下,两个连续的项目编号不同 - 立即打破循环(跳转到next行)并打印&#34;正确&#34 ;行

  • if(n!=1){ print } - 如果该行中的所有项目编号没有差异(具有相同的值)且其值不等于1 - 打印该行,否则 - 该行赢了& #39;打印

答案 2 :(得分:0)

$ grep -E ' (1[0-9]|[2-9])' file
GROUP2, 1350 Red.apple, 1 Black.pencil, 1 Blue.pen, 1 Green.pen, 1 Little.tree,
GROUP30, 2 Green.bow, 4 Big.tree,
GROUP170, 1 Yellow.banana, 2 Green.apple, 1 Blue.skirt, 1 Purple.top, 1 Silver.shoe,
GROUP6, 2 Tall.hat, 2 Bow.tie, 2 Shiny.shoe,
GROUP7, 20 Red.apple, 20 Black.pencil, 20 Blue.pen, 20 Green.pen, 20 Little.tree,