2016-09-06 12 views
8

私はsedでいくつかのbase64置換をしようとしています。Sedは、キャプチャグループを引数として使用してbashコマンドの出力に置き換えます。

は私がやろうとしていることはこれです:

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" 

をそして、私は交換したいですベーステキストはプレーンテキストで

someline 
someline 
Base64Expression stringValue="foo" 
someline 
Base64Expression stringValue="bar" 
将来的には

私はawkの使用を開始しましたが、私はそれがSEDと単純(とはるかにエレガント)得ることができるものの、後方操作(復号されたファイルにBASE64で文字列をコードする)

を行う必要があるでしょう。

#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 
+0

'$(echo" \ 2 "| base64 -d)'が最初に実行されるため、これはできません。さらに、sed内でシェル変数を使用する場合は一重引用符を二重引用符に置き換える必要があります。 – sjsam

+0

awk'そのような処理のために設計されている。しかし、私たちはあなたの問題を、あなたの助けとなるように入力を与えられたあなたの必要な出力として再現するために、サンプルデータの最小セットを見る必要があります。その情報を含めるようにQを編集してください。がんばろう。 – shellter

+0

@shellter私はawkでやったことを使って自分の質問を編集しました。 @ sjsam、引用符を指摘してくれてありがとう、私もそれを編集しました。 – statox

答えて

11

あなたは評価のためのシェルに置換文字列を渡すためにGNU sedeを使用することができます($bundleは私が編集していたファイルである。)これまでのawkで私はこれを持っています。このように、あなたが言うことができます:

\1がキャプチャグループを保持している
printf "%s %s" "something" "\1" 

。すべて一緒に:

これは、この場合のように、キャプチャされたグループでいくつかのシェルアクションを実行する場合に便利です。

このように、行の最初の部分をキャプチャし、次にエンコードする必要のある部分と残りの部分をキャプチャしましょう。どのように

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

アイデアは、このsuperb answer by anubhavaから来ている:ステップバイ

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

ステップ:これが完了すると、のprintfが第二のスライスに対してbase64 -dの使用をトリガとバックそれらの作品を印刷してみましょうsedの日付形式を変更しますか?

+1

これは素晴らしいsedスキルです! 'e'フラグと' printf'を組み合わせたトリックは私の必要なものです!どうもありがとう! – statox

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が正しいアプローチであると仮定。

+0

'{print}'文がどのように使われているか分かりません。私はawkのベテランではなく、正規表現や 'BEGIN | END'を使わずに使われているので、私は困惑してしまいます。コードがどのように動作するかを少し説明することができれば、本当に素晴らしいことです。 – statox

+0

私はあなたのコードをコピーし、構文を修正して 'print'を追加しました。 Awkは ' {}'ステートメントで構成されています。デフォルトの条件はtrueで、デフォルトのアクションは現在のレコード(デフォルトでは行)を出力します。スクリプト内の '{print}'はすべての行を表示するだけです。 Arnold Robbinsの「Effective Awk Programming」第4版をお勧めします。 –

+1

書き直してくれてありがとう、今はっきりしています。そして、私は間違いなくこの本を探します。 – statox

関連する問題