【问题标题】:Regexp for removing certain columns用于删除某些列的正则表达式
【发布时间】:2017-02-17 16:08:31
【问题描述】:

我有一个这种格式的输入:

<apple1> <orange1> : <apple2> <orange2> : <apple3> <orange3> : ...

此输入的长度未定义,由带有不同橙色和苹果部分的苹果-橙色对组成,用冒号分隔。

我想把它作为输出:

<apple1> <orange1> : <orange2> : <orange3> : ...

我。 e.除第一个外的所有苹果部件。

每个苹果部分宽 14 个字符,每个橙色部分宽 19 个字符。

我尝试过这样的事情:

sed -r 's/.{14}(.{19}):/\1:/g'

但这总是会遇到跳过第一个苹果部分的问题。

谁能提供一个正则表达式来解决这个任务?

真实世界示例输入:

appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo
foofoofoofoofobarbarbarbarbarbarb:foofoofoofoofobarbarbarbarbarbarb:foofoofoofoofobarbarbarbarbarbarb
xxxxxxxxxxxxxxooooooooooooooooooo:ppppppppppppppqqqqqqqqqqqqqqqqqqq:nnnnnnnnnnnnnnttttttttttttttttttt

输出应该是这样的:

appleappleapplorangeorangeorangeo:orangeorangeorangeo:orangeorangeorangeo
foofoofoofoofobarbarbarbarbarbarb:barbarbarbarbarbarb:barbarbarbarbarbarb
xxxxxxxxxxxxxxooooooooooooooooooo:qqqqqqqqqqqqqqqqqqq:ttttttttttttttttttt

【问题讨论】:

  • pipe symbol 在哪里?
  • 抱歉,编辑太疯狂了。我的意思是冒号。问题已编辑。
  • 你是如何存储输出的?这很重要,因为您可以执行head -c 14 之类的操作来将第一个苹果放入输出中。
  • 就此而言,您的输入是什么样的?
  • @Alfe 你能发布一个真实的例子吗?我的意思是,对于真正的苹果/橙子,3-4 列就足够了

标签: regex shell sed


【解决方案1】:

您对 sed 的正则表达式几乎是正确的。一遍又一遍地匹配 ":_14_19" 并删除 14 部分。 (注意:我在下面使用逗号作为正则表达式分隔符,因为它们更容易阅读。)

$ export A='appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo:foofoofoofoofobarbarbarbarbarbarb:foofoofoofoofobarbarbarbarbarbarb:foofoofoofoofobarbarbarbarbarbarb:xxxxxxxxxxxxxxooooooooooooooooooo:ppppppppppppppqqqqqqqqqqqqqqqqqqq:nnnnnnnnnnnnnnttttttttttttttttttt'
$ echo $A | sed -Ee 's,:.{14}(.{19}),:\1,g'
appleappleapplorangeorangeorangeo:orangeorangeorangeo:orangeorangeorangeo:barbarbarbarbarbarb:barbarbarbarbarbarb:barbarbarbarbarbarb:ooooooooooooooooooo:qqqqqqqqqqqqqqqqqqq:ttttttttttttttttttt

【讨论】:

  • 是的,我认为如果没有更好的消息出现,我认为这会起作用。我希望不要依赖某些行中有冒号这一事实,但由于它们是我规范的一部分,我认为这是最短的解决方案。
【解决方案2】:

这项工作更适合awk,因为输入文件在行和列中结构良好,使用已知的分隔符,即colon

awk 'BEGIN{FS=OFS=":"} {for (i=2; i<=NF; i++) $i = substr($i, 15)} 1' file

appleappleapplorangeorangeorangeo:orangeorangeorangeo:orangeorangeorangeo
foofoofoofoofobarbarbarbarbarbarb:barbarbarbarbarbarb:barbarbarbarbarbarb
xxxxxxxxxxxxxxooooooooooooooooooo:qqqqqqqqqqqqqqqqqqq:ttttttttttttttttttt

此 awk 命令使用: 作为输入+输出分隔符,并从每条记录的第二个字段开始,它将每个字段设置为来自15th 位置的同一字段的子字符串。

【讨论】:

    【解决方案3】:

    使用 perl..

    我们的意见appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo

    假设 a=appleappleappl(14 个字符) b=orangeorangeorangeo(19 个字符) c=appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo(该行的其余部分,是 ab 的重复组合。

    预期输出: 在第一个冒号 (:) 之前,ab 都保留,在第一个冒号之后,只保留 b。 ${a}${b}:${b}:${b}:....(如果我错了,请纠正我)

    所以这里再次回顾一下输入和输出。

    我们的意见: appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo

    预期输出: appleappleapplorangeorangeorangeo:orangeorangeorangeo:orangeorangeorangeo

    请试试这个脚本:(如前所述,这是使用 perl 而不是 shell)。

    %_Host@User> cat apple.pl
    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    while (<>) {
      chomp $_ ;
      my @tmp = split /:/, $_ ;
      my ($a,$b) = (substr($tmp[0],0,14), substr($tmp[0],14,19)) ;
      my $str = "$a"."$b" ;
    
      foreach my $i (1..$#tmp) {
        $tmp[$i] =~  s/$a//g ;
        $str .= ":"."$tmp[$i]"  ;
      }
      print "$str\n" ;
    }
    %_Host@User>
    

    脚本输出:

    %_Host@User> cat td_apple |./apple.pl
    appleappleapplorangeorangeorangeo:orangeorangeorangeo:orangeorangeorangeo
    foofoofoofoofobarbarbarbarbarbarb:barbarbarbarbarbarb:barbarbarbarbarbarb
    xxxxxxxxxxxxxxooooooooooooooooooo:ppppppppppppppqqqqqqqqqqqqqqqqqqq:nnnnnnnnnnnnnnttttttttttttttttttt
    

    样本数据:

    %_Host@User> cat td_apple
    appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo:appleappleapplorangeorangeorangeo
    foofoofoofoofobarbarbarbarbarbarb:foofoofoofoofobarbarbarbarbarbarb:foofoofoofoofobarbarbarbarbarbarb
    xxxxxxxxxxxxxxooooooooooooooooooo:ppppppppppppppqqqqqqqqqqqqqqqqqqq:nnnnnnnnnnnnnnttttttttttttttttttt
    %_Host@User>
    

    谢谢。

    【讨论】:

    • 哇。好多啊。谢谢,但使用正则表达式的整个想法是保持它小而简单。抱歉,您的解决方案在这方面有点不合时宜。
    • 你是对的!不能不同意那里。是的,这个解决方案不小;P。
    • @Alfe:请问您,您需要处理多少这种特定类型的数据?你的方案是什么,可以分享一些信息。
    • 我有大约 40 行输入(准确地说是每季度 ;-)
    猜你喜欢
    • 2017-02-20
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-19
    相关资源
    最近更新 更多