【问题标题】:Substitution with sed + bash function用 sed + bash 函数替换
【发布时间】:2011-04-25 09:49:52
【问题描述】:

我的问题似乎很笼统,但我找不到任何答案。

在 sed 命令中,如何将替换模式替换为简单 bash 函数返回的值。

例如,我创建了以下函数:

function parseDates(){
    #Some process here with $1 (the pattern found)
    return "dateParsed;
}

以及下面的 sed 命令:

myCatFile=`sed -e "s/[0-3][0-9]\/[0-1][0-9]\/[0-9][0-9]/& parseDates &\}/p" myfile`

我发现字符 '&' 代表找到的当前模式,我希望将它传递给我的 bash 函数,并将整个模式替换为找到的模式 +dateParsed。

有人有想法吗? 谢谢

【问题讨论】:

    标签: bash sed substitution


    【解决方案1】:

    您可以像这样在 sed 命令中使用“e”选项:

    cat t.sh
    
    myecho() {
            echo ">>hello,$1<<"
    }
    export -f myecho
    sed -e "s/.*/myecho &/e" <<END
    ni
    END
    

    你可以看到没有“e”的结果:

    cat t.sh
    
    myecho() {
            echo ">>hello,$1<<"
    }
    export -f myecho
    sed -e "s/.*/myecho &/" <<END
    ni
    END
    

    【讨论】:

    • 无法识别选项“e”。我还尝试通过 export -f parseDate 导出我的函数,但它不起作用。这个例子不适合我。
    • 我只好折腾改成$(myecho)
    【解决方案2】:

    同意格伦杰克曼的观点。 如果你想在 sed 中使用 bash 函数,像这样:

    sed -rn 's/^([[:digit:].]+)/`date -d @&`/p' 文件 | 同时读取 -r 行;做 评估回声“$行” 完毕

    我的文件以 unix 时间戳开头(例如 1362407133.936)。

    【讨论】:

      【解决方案3】:

      sed 中的 Bash 函数(可能用于其他目的):

      multi_stdin(){ #Makes function accepet variable or stdin (via pipe)
          [[ -n "$1" ]] && echo "$*" || cat -
      }
      
      sans_accent(){ 
          multi_stdin "$@" | sed '
              y/àáâãäåèéêëìíîïòóôõöùúûü/aaaaaaeeeeiiiiooooouuuu/
              y/ÀÁÂÃÄÅÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜ/AAAAAAEEEEIIIIOOOOOUUUU/
              y/çÇñÑߢÐð£Øø§µÝý¥¹²³ªº/cCnNBcDdLOoSuYyY123ao/
          '
      }
      
      eval $(echo "Rogério Madureira" | sed -n 's#.*#echo & | sans_accent#p')
      

      eval $(echo "Rogério Madureira" | sed -n 's#.*#sans_accent &#p')
      
      Rogerio
      

      如果您需要将输出保存到变量中:

      VAR=$( eval $(echo "Rogério Madureira" | sed -n 's#.*#echo & | desacentua#p') )
      echo "$VAR"
      

      【讨论】:

        【解决方案4】:

        一步一步来。 (您也可以使用备用分隔符,例如“|”而不是“/”

        function parseDates(){
            #Some process here with $1 (the pattern found)
            return "dateParsed;
        }
        
        value=$(parseDates)
        sed -n "s|[0-3][0-9]/[0-1][0-9]/[0-9][0-9]|& $value &|p" myfile
        

        注意使用双引号而不是单引号,这样可以对$value进行插值

        【讨论】:

        • 我相信所要求的是将匹配的模式作为参数传递给 bash 函数。
        • dateParsed 不需要打开 " 或关闭一个,而不是“return”,它只能返回一个 int、一个 echo 或 printf。
        【解决方案5】:

        我也想知道是否有办法做到这一点。但是,对于这个特定问题,您不需要它。如果你用()s 包围日期的不同部分,你可以用\1 \2 等来引用它们,然后根据需要重新格式化。

        例如,让我们反转 03/04/1973:

        echo 03/04/1973 | sed -e 's/\([0-9][0-9]\)\/\([0-9][0-9]\)\/\([0-9][0-9][0-9][0-9]\)/\3\/\2\/\1/g'
        

        【讨论】:

        • 如果您想整理命令中的 /s,sed 可以接受 / 以外的字符作为替换结构 (s///),例如以下内容应等同于您的示例:echo 03/04/1973 | sed -e 's#\([0-9][0-9]\)/\([0-9][0-9]\)/\([0-9][0-9][0-9][0-9]\)#\3/\2/\1#g'
        【解决方案6】:
        sed -e 's#[0-3][0-9]/[0-1][0-9]/[0-9][0-9]#& $(parseDates &)#' myfile |
        while read -r line; do
            eval echo "$line"
        done
        

        【讨论】:

          【解决方案7】:

          您可以通过结束单引号部分并重新打开它来将 sed 命令粘合在一起。

          sed -n 's|[0-3][0-9]/[0-1][0-9]/[0-9][0-9]|& '$(parseDates)' &|p' datefile
          

          但是,与其他示例相比,bash 中的函数不能返回字符串,只能将它们输出:

          function parseDates(){
              # Some process here with $1 (the pattern found)
              echo dateParsed
          }
          

          【讨论】:

          • 我仍然对这个解决方案有疑问。调用 bash 函数。但是参数 & 似乎没有被正确复制到函数中,因为我不能使用 $1 来引用 &。
          • 哦,对不起,但上面的解决方案是针对一个不只接受参数的函数,并且在 sed 命令之前进行评估。另一种可能性是,稍后再调用它$(script $(sed 'sedcmd' file))
          猜你喜欢
          • 2011-12-02
          • 2021-11-20
          • 2013-08-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-23
          • 1970-01-01
          • 2020-02-03
          相关资源
          最近更新 更多