使用捕获组作为参数

时间:2016-09-06 12:27:39

标签: bash sed

我正在尝试使用sed进行一些base64替换。

我想做的是:

sed -i "s|\(some\)\(pattern\)|\1 $(echo "\2" | base64 -d)|g" myFile

用英语表示:

  • 数学模式
  • 捕获群组
  • 在bash命令中使用捕获的组
  • 使用此命令的输出作为替换字符串

到目前为止,我的命令不起作用,因为\2仅由sed而不是我正在调用的bash命令知道。

我必须将捕获组传递给我想要使用输出的命令,这是一个优雅的解决方案吗?

修改

以下是我正在尝试做的最小例子:

我有以下文件:

someline
someline
Base64Expression stringValue="Zm9v"
someline
Base64Expression stringValue="YmFy"

我想用纯文本替换base64:

someline
someline
Base64Expression stringValue="foo"
someline
Base64Expression stringValue="bar"

将来我将不得不进行向后操作(在解码文件的base64中编码字符串)

我已经开始使用awk但是我用sed可以变得更简单(更优雅)。到目前为止,我有awk(其中$bundle是我正在编辑的文件):

#For each line containing "Base64Expression"
#Put in the array $substitutions[]:
# The number of the line (NR)
# The encoded expression ($2)
# The decoded expression (x)
substitutions=($(awk -v bd=$bundle '
    BEGIN {
        # Change the separator from default
        FS="""
        ORS=","
        OFS=","
    }
    /Base64Expression/ {
        #Decode the base64 lines
        cmd="echo -ne \""$2"\" | base64 -d"
        cmd | getline x

        if ( (cmd | getline) == 0 ){
            print NR, $2, x
        }
    }
' $bundle))

# Substitute the encoded expressions by the decoded ones
# Use the entries of the array 3 by 3
# Create a sed command which takes the lines numbers
for ((i=0; i<${#substitutions[@]}; i+=3))
do
    # Do the substitution only if the string is not empty
    # Allows to handle properly the empty variables
    if [ ${substitutions[$((i+1))]} ]
    then
        sed -i -e "${substitutions[$i]}s#${substitutions[$((i+1))]}#${substitutions[$((i+2))]}#" $bundle
    fi
done

2 个答案:

答案 0 :(得分:12)

您可以在GNU e中使用sed将替换字符串传递给shell进行评估。这样,您可以说:

printf "%s %s" "something" "\1"

\1包含捕获的组的位置。一起来:

$ sed -r 's#match_([0-9]*).*#printf "%s %s" "something" "\1"#e' <<< "match_555 hello"
something 555

当您想要对捕获的组执行某些shell操作时,这很方便,就像这种情况一样。

所以,让我们捕捉线的第一部分,然后是需要编码的部分,最后是剩下的部分。完成此操作后,让我们打印这些部分,printf触发对第二个切片使用base64 -d

$ sed -r '/^Base64/s#(.*;)([^\&]*)(&.*)# printf "%s%s%s" "\1" $(echo "\2" | base64 -d) "\3";#e' file
someline
someline
Base64Expression stringValue=&quot;foo&quot;
someline
Base64Expression stringValue=&quot;bar&quot;

一步一步:

sed -r '/^Base64/s#(.*;)([^\&]*)(&.*)# printf "%s%s%s" "\1" $(echo "\2" | base64 -d) "\3";#e' file
#        ^^^^^^^    ^^^  ^^^^^^  ^^^                        ^^^^^^^^^^^^^^^^^^^^^^^^       ^
#           |   first part  |   the rest                encode the 2nd captured group      |
#           |               |                                                              |
#           |           important part                                      execute the command
#           |
# on lines starting with Base64, do...

这个想法来自如何在sed中更改日期格式的superb answer by anubhava

答案 1 :(得分:3)

听起来这就是你正在尝试做的事情:

$ cat tst.awk
BEGIN { FS=OFS="&quot;" }
/^Base64Expression/ {
    cmd="echo -ne \""$2"\" | base64 -d"
    if ( (cmd | getline x) > 0 ) {
        $2 = x
    }
    close(cmd)
}
{ print }

$ awk -f tst.awk file
someline
someline
Base64Expression stringValue=&quot;foo&quot;
someline
Base64Expression stringValue=&quot;bar&quot;

假设您的echo | base64是正确的做法。