sed:文字列を変数の内容に置き換える

sed:文字列を変数の内容に置き換える

{?varname}特定のパターン()の文字列を見つけて、その環境変数に置き換えるスクリプトを作成しようとしています。

これが私が今まで持っているものです:

function get_env() {
   var=$1
   echo ${!var}
}

sed -e 's/{?\([a-z]*}\)/'$(get_env '\1')'/g' file.txt

この関数は次のように動作しますget_env LOGNAME-->dotan

echo __$1__sed は関数の値を返します。たとえば、関数の内容をI will getに置き換えると{?logname}- >__LOGNAME__

しかし、組み合わせると動作しません。これは、関数が常に空の文字列を返すのと同じです。

ここで問題の原因が何であるかよくわかりません。どんなアイデアがありますか?

答え1

コマンドラインはget_env '\1'コマンド置換で実行され、その出力はに貼り付けられます。変数の有効な名前ではないため、sedエラーが発生する可能性があります。\1

s/\{\?([a-z]+)\}/$ENV{$1}/Perlを使用してこれを行うことができます。%ENVこれは環境変数を含むハッシュです。

$ export name=you
$ echo "hello {?name}" | perl -pe 's/\{\?([a-z]+)\}/$ENV{$1}/'
hello you

(GNU sedにはe外部プログラムを実行するコマンドがありますが、一致する部分だけではなくパターンスペース全体を実行するため、これには適していないようです)。


純粋にBashで()を主張する場合setvar.sh

#!/bin/bash
while IFS= read -r line ; do
        while [[ $line =~ ^(.*)(\{\?[a-zA-Z0-9_]+\})(.*)$ ]] ; do
                varname=${BASH_REMATCH[2]}
                varname=${varname#"{?"}
                varname=${varname%\}}
                printf -v line "%s%s%s" "${BASH_REMATCH[1]}" "${!varname}" "${BASH_REMATCH[3]}"
        done
        printf "%s\n" "$line" 
done < "${1-/dev/stdin}"

$ echo 'foo {?BASH_VERSION} {?blah} bar' |blah=ABC bash setvar.sh
foo 4.4.12(1)-release ABC bar

答え2

これが私が思いついた解決策です

grep -o '{?\S*}' file.txt | sed 's/{?\(.*\)}/\1/' | xargs -I {} sh -c "sed -i -e 's/{?"{}"}/'$"{}"'/' file.txt"

それを破壊する:

  • grep -o '{?\S*}' file.txt- 置き換えるすべての変数を取得します。
  • sed 's/{?\(.*\)}/\1/'- フォーマットの削除
  • xargs -I {} sh -c "sed -i -e 's/{?"{}"}/'$"{}"'/' file.txt"- 各変数を個別に検索して置換

関連情報