【问题标题】:Find number, and remove adjacent characters equal to this number查找数字,并删除等于该数字的相邻字符
【发布时间】:2012-06-26 12:42:33
【问题描述】:

我的 4 列输出的一部分如下所示:

5    cc1kcc1kc    5    cc1kcc1kc
5    cc2ppggg   5    cc2ppggg
6    ccg12qqqqqqqqqqqqggg    10 ccccg11qqqqqqqqqqqggggg 
3    4qqqqcgc1q   12    cgccgccgccgc

我只想更改第二列和第四列,有没有办法使用 awk/sed 删除旁边有字符的数字? 或者使用 perl 脚本来执行这种转换会更容易/更好吗?

生成的输出应如下所示:

5    ccccc    5    ccccc
5    ccggg    5    ccggg
6    ccgggg   10    ccccgggggg 
3    cgc    12    cgccgccgccgc

【问题讨论】:

    标签: perl unix sed awk


    【解决方案1】:

    perl:

    perl -pe 's/\d+([^\d\s])\1*//g'
    

    【讨论】:

    • +1 因为这样可以完成工作,但稍微解释一下就好了。
    • 好的。选项-p 使Perl 假定围绕您的代码进行以下循环(选项-e 和单线),这使其迭代参数有点像sed。和正则表达式描述见answer about sed
    • 删除第 3 行和第 4 行第 3 列中的“10”和“12”。
    【解决方案2】:

    使用 sed:

    sed 's/[0-9]\+\([a-z]\)\1*//g'
    

    匹配找到任何数字字符串 ([0-9]+) 后跟任何字母 ([a-z])。 \1* 匹配该字符的任何后续出现。 /g(全局)修饰符确保每行多次替换。

    【讨论】:

      【解决方案3】:

      从字面上看,这会从字段 2 和 4 中删除任何 n 的下一个 n 个字符嵌入现场。

      perl -lane 'for $i (1, 3) {@nums = $F[$i] =~ /(\d+)/g; for $num (@nums) {$F[$i] =~ s/$num.{$num}//}}; print join("\t", @F)'
      

      其他答案删除数字和所有相同的字符。

      为了说明我的答案与其他答案之间的区别,请使用以下输入:

      6    ccg8qqqqqqqqqqqqggg    10 ccccg3qqqqqqqqqqqggggg
      

      我的版本输出如下:

      6    ccgqqqqggg     10      ccccgqqqqqqqqggggg
      

      虽然他们的输出是这样的:

      6    ccgggg    10 ccccgggggg
      

      【讨论】:

        【解决方案4】:

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

        sed 'h;s/\S*\s*\(\S*\).*/\1/;:a;s/[^0-9]*\([0-9]\+\).*/sed "s|\1.\\{\1\\}||" <<<"&"/e;ta;H;g;/\n.*\n/bb;s/\(\S*\s*\)\{3\}\(\S*\).*/\2/;ba;:b;s/^\(\S*\s*\)\(\S*\)\([^\n]*\)\n\(\S*\)/\1\4\3/;s/\(\S*\s*\)\n\(.*\)/\2/' file
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-06-29
          • 2021-10-16
          • 1970-01-01
          • 2016-01-12
          • 2014-01-15
          • 2023-03-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多