【问题标题】:complex text replace from the command line从命令行替换复杂文本
【发布时间】:2011-05-11 16:46:24
【问题描述】:

我想要做的简化示例:

我有一个文件:input.txt,看起来像

a 2 4 b
a 3 8 b
c 9 4 d
a 3 4 8 b

还有一个脚本:add.sh,它接受命令行参数并返回它们的总和

我想在 input.txt 中搜索模式 'a (.*) b' 的所有实例,其中我将 (.*) 部分作为命令行参数传递给 add.sh。

例如,我想做sed 's/a \(.*\) b/a {add.sh \1} b/g' input.txt之类的事情 (这当然行不通)。 所以输出应该是这样的

a 6 b
a 11 b
c 9 4 d
a 15 b

最简单的方法是什么?

谢谢

【问题讨论】:

    标签: regex command-line sed


    【解决方案1】:

    如果add.sh 是:

    #!/bin/sh
    arg1=$1
    nums=$2
    shift 2
    for i in $nums
    do
        sum=$((sum+i))
    done
    echo "$arg1 $sum $@"
    

    那么你可以这样做:

    sed 's/^\([^ ]* \)\(.*\)\( [^ ]*\)$/\1\"\2\"\3/' input.txt | xargs -L 1 ./add.sh
    

    这将在每一行添加数字。要仅为以“a”开头并以“b”结尾的行添加它们,请使用:

    sed 's/^a \(.*\) b$/a \"\1\" b/' input.txt | xargs -L 1 ./add.sh
    

    “c 9 4 d”行仍由add.sh 处理,但sed 命令不添加任何引号,因此脚本仅将“9”视为$2,因此总和仅完成一次,结果为“9”。 “4”被视为$@ 其余部分的一部分。

    【讨论】:

      【解决方案2】:

      如果 perl 不是一个选项,你可以 编写如下脚本:

      grep -e '^a .* b$' input.txt | sed -e 's/a \(.*\) b/\1/g' | while read LINE; do ./add.sh $LINE; done
      

      我意识到以上并没有解决你的问题,我只是专注于你的 sed 表达。

      但是,如果您热衷于使用另一个 shell 脚本来解决这个问题,它可能看起来像这样:

      cat input.txt | while read LINE; do
          if [[ "$LINE" =~ ^a (.*) b$ ]]; then
              echo -n "a "
              add.sh ${BASH_REMATCH[1]}
              echo " b"
          else
              echo $LINE
          fi
      done
      

      【讨论】:

        【解决方案3】:
        perl -pe 's/a (.*) b/"a ".`add.sh $1`." b"/eg' input.txt
        

        只要确保 add.sh 不输出换行符即可。

        【讨论】:

          猜你喜欢
          • 2011-06-26
          • 2014-12-28
          • 2021-07-06
          • 2013-02-24
          • 1970-01-01
          • 2013-11-20
          • 1970-01-01
          • 2011-03-25
          • 2017-08-23
          相关资源
          最近更新 更多