Sed replace with the output of a bash command using capture group as argument

前端 未结 2 2011
遥遥无期
遥遥无期 2020-12-15 21:35

I\'m trying to make some base64 substitution with sed.

What I\'m trying to do is this:

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


        
相关标签:
2条回答
  • 2020-12-15 21:57

    You can use e in GNU sed to pass the substitution string to a shell for evaluation. This way, you can say:

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

    Where \1 holds a captured group. All together:

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

    This comes handy when you want to perform some shell action with a captured group, like in this case.

    So, let's capture the first part of the line, then the part that needs to be encoded and finally the rest. Once this is done, let's print those pieces back with printf triggering the usage of base64 -d against the second slice:

    $ 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;
    

    Step by step:

    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...
    

    The idea comes from this superb answer by anubhava on How to change date format in sed?.

    0 讨论(0)
  • 2020-12-15 21:59

    It sounds like this is what you're trying to do:

    $ 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;
    

    assuming your echo | base64 is the right approach.

    0 讨论(0)
提交回复
热议问题