{?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"
- 各変数を個別に検索して置換