【问题标题】:selectively delete lines选择性地删除行
【发布时间】:2012-03-31 19:44:15
【问题描述】:

我有一个文本文件,其中包含跨 16 列的制表符分隔数据。 我想删除在第 6 列中找到值 1260、1068 和 907 的完整行。

9513    2010-06-15 17:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-15 18:00:02 \N
9523    2010-06-15 18:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-15 19:00:02 \N
9534    2010-06-15 19:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-15 20:00:02 \N
9543    2010-06-15 20:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-15 21:00:02 \N
9552    2010-06-15 21:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-15 22:00:02 \N
9560    2010-06-15 22:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-15 23:00:02 \N
9569    2010-06-15 23:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-16 00:00:02 \N
9579    2010-06-16 00:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-16 01:00:02 \N
9589    2010-06-16 01:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-16 02:00:01 \N
9599    2010-06-16 02:00:00 94  0   69  12  0   0   0   0.0000  0   \N  \N  \N  2010-06-16 03:00:02 \N
95642733    2011-10-19 19:00:00 4341    0   1263    0   11  0   0   0.0000  0   \N  \N  \N  2011-10-19 20:05:06 \N
95642732    2011-10-19 19:00:00 4341    0   1260    0   24635   0   0   0.0000  0   \N  \N  \N  2011-10-19 20:05:06 \N
95642540    2011-10-19 19:00:00 4050    0   1068    103 113 2   0   0.0000  0   \N  \N  \N  2011-10-19 20:05:06 \N
95642539    2011-10-19 19:00:00 4050    0   907 19  0   0   0   0.0000  0   \N  \N  \N  2011-10-19 20:05:06 \N

【问题讨论】:

  • 如果这不是经常发生的事情,为什么不将数据加载到文本编辑器中并删除不需要的行。 (数据有多大,是否必须在大量文件中持续删除具有这些值的行?)
  • 文件中是否有任何空格字符,或者我们可以只考虑“空白”作为您的字段分隔符?

标签: sed awk grep


【解决方案1】:

Awk 是您要使用的工具。

awk '$6==1260 || $6==1068 || $6==907 {next} {print}'

这是做什么的?

Awk 在文件的每一行上运行一段代码。代码以一个必须计算为真的表达式开始(在本例中是第 6 个字段的三个可能值),然后是大括号中的命令。在这种情况下,命令next 告诉它继续下一个输入行而不运行任何其他命令。

如果三个比较失败,并且我们没有运行next,那么我们打印该行。

【讨论】:

    【解决方案2】:

    您想要我们的是awk。 awk 是 UNIX 中一种非常强大的语言,如果您遇到复杂的测试流问题,awk 是您的解决方案。

    试试这个脚本:

    awk '{
    if ($6 != 1260 || $6 != 1068 || $6 != 907)
       print $0;
    }' file.txt >> output_file.txt
    

    【讨论】:

    • 他不想消除第 6 列,他想消除行。
    • 是的,我写到一半忘记了。它已修复。
    【解决方案3】:

    这可能对你有用(GNU sed?):

    sed '/^\(\S*\s*\)\{5\}\(1260\|1068\|907\)\s/d' file
    

    或一般来说:

    sed '/^\([^[:space:]]*[[:space:]]*\)\{5\}\(1260\|1068\|907\)[[:space:]]/!d'
    

    【讨论】:

    • AFAIK,{n} 符号只是 ERE,所以这可以在 Linux 中使用 sed -r 完成(调整反斜杠),但仅此而已。如果您切换到完整的字符类名称或只是将制表符直接放入正则表达式中,则可能在 FreeBSD 中工作。
    • @ghoti 我认为 \{m,n\} 是 POSIX BRE 参见 here
    • 啊,没错。那么,只有\S\s 会导致问题。
    • @ghoti 你可能是对的,但如果我使用--posix 开关运行相同的解决方案,我会得到相同的结果。
    • 这仍然是您的 sed 实现。 FreeBSD 的 sed 理解 \s\S 无论您的版本使用 --posix 选项做什么。
    【解决方案4】:
    awk '$6!=1260 && $6!=1068 && $6!=907' file
    

    【讨论】:

    • 当字符串相等时不需要正则表达式。另外,例如,此答案还将删除包含 9070 的行。
    猜你喜欢
    • 2013-03-21
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 2013-09-07
    相关资源
    最近更新 更多