用AWK删除特定行[或sed,grep,等等]

时间:2015-04-02 20:24:43

标签: regex linux bash awk sed

是否可以使用awk从文件中删除行?我想找到最后一列中有Y的任何行,然后删除与所述行的第2列中的值匹配的所有行。

之前:

KEY1,TRACKINGKEY1,TRACKINGNUMBER1-1,PACKAGENUM1-1,N
    ,TRACKINGKEY1,TRACKINGNUMBER1-2,PACKAGENUM1-2,N
KEY1,TRACKINGKEY1,TRACKINGNUMBER1-1,PACKAGENUM1-1,Y
    ,TRACKINGKEY1,TRACKINGNUMBER1-2,PACKAGENUM1-2,Y
KEY1,TRACKINGKEY5,TRACKINGNUMBER1-3,PACKAGENUM1-3,N
KEY2,TRACKINGKEY2,TRACKINGNUMBER2-1,PACKAGENUM2-1,N
KEY3,TRACKINGKEY3,TRACKINGNUMBER3-1,PACKAGENUM3-1,N
    ,TRACKINGKEY3,TRACKINGNUMBER3-2,PACKAGENUM3-2,N

所以awk会发现第3行在最后一列中有Y,然后查看第2列[TRACKINGKEY1]并删除第2列中包含TRACKINGKEY1的所有行。

预期结果:

KEY1,TRACKINGKEY5,TRACKINGNUMBER1-3,PACKAGENUM1-3,N
KEY2,TRACKINGKEY2,TRACKINGNUMBER2-1,PACKAGENUM2-1,N
KEY3,TRACKINGKEY3,TRACKINGNUMBER3-1,PACKAGENUM3-1,N
    ,TRACKINGKEY3,TRACKINGNUMBER3-2,PACKAGENUM3-2,N

这样做的原因是我们的装运程序会在处理货件时以及当货物无效时发出文件[如果发生错误]。所以我最终得到的是最初的包裹信息,然后是相同的信息,表明它已经无效,然后是另一组带有新货物信息的行。不幸的是,我们的ERP软件有一种相当简单的脚本语言,我甚至无法创建一个数组,所以我只能使用shell工具。

提前致谢!

2 个答案:

答案 0 :(得分:1)

一种方法是使用awk将#传递给同一个文件:

awk -F, 'NR == FNR && $NF=="Y" && !($2 in seen){seen[$2]} 
          NR != FNR && !($2 in seen)' file file
KEY1,TRACKINGKEY5,TRACKINGNUMBER1-3,PACKAGENUM1-3,N
KEY2,TRACKINGKEY2,TRACKINGNUMBER2-1,PACKAGENUM2-1,N
KEY3,TRACKINGKEY3,TRACKINGNUMBER3-1,PACKAGENUM3-1,N
    ,TRACKINGKEY3,TRACKINGNUMBER3-2,PACKAGENUM3-2,N

<强>解释

NR == FNR                    # if processing the file 1st time
&& $NF=="Y"                  # and last field is Y
&& !($2 in seen) {           # we haven't seen field 2 before
  seen[$2]}                  # store field 2 in array seen
}
NR != FNR                    # when processing the file 2nd time
&& !($2 in seen)             # array seen doesn't have field 2
                             # take default action and print the line

答案 1 :(得分:1)

这种解决方案有点粗糙,但很有趣。

grep ',Y$' file | cut -d, -f2 | sort -u | grep -vwFf - file
  • grep ',Y$' file - 在最后一栏中找到带有Y的行
  • cut -d, -f2 - 只打印这些行中的跟踪键
  • sort -u - 只提供唯一键
  • grep -vwFf - file -
    • 从stdin(-f -
    • 中读取唯一的跟踪键
    • 如果他们是整个单词(-w
    • ,则只考虑他们匹配
    • 它们是固定字符串,而不是正则表达式(-F
    • 然后从文件
    • 中排除与这些模式(-v)匹配的行