2013-10-25 8 views
5

sedを使用して、%XXX%形式のファイルのテンプレート文字列をシェルスクリプトのXXXという変数の値に置き換えようとしています。sedを使ってファイル内の文字列をその名前の変数の内容に置き換えます

以下の作品は完全

sed "s/%user_home%/$user_home/gi" 

のでuser_home=fred以下、

NameVirtualHost *:80 

<VirtualHost *:80> 
    ServerName %server_name% 

    ErrorLog /var/log/apache2/%user_home%_webapp_error.log 
    CustomLog /var/log/apache2/%user_home%_webapp.log common 

    DocumentRoot /home/%user_home%/web_app/public 
</VirtualHost> 

は、問題は、私は明示的にテンプレートの文字列を知らなくても、sedのコマンドを実行したいということです、

NameVirtualHost *:80 

<VirtualHost *:80> 
    ServerName %server_name% 

    ErrorLog /var/log/apache2/fred_webapp_error.log 
    CustomLog /var/log/apache2/fred_webapp.log common 

    DocumentRoot /home/fred/web_app/public 
</VirtualHost> 

になった場合とその変数が前面に表示されます。つまり、変数の実際の名前が何であるかを気にせずに、%XXX%を探して、$ XXXの内容で置き換えます。

バックリファレンスと何か関係がありますが、バックリファレンスの内容を変数名として使用する方法を理解できません。

私は

sed "s/%\([a-z_]\)%/$(\1)/gi" 
を試みたが、それは$ \ 1という変数を探しているように見えるので、これは動作しませんでした。

+1

バッククォートが動作しません、問題なく変更することができました。変数は 'sed'に引数を送る前にシェルによって展開されます。 – Barmar

+1

これにはPerlが適しています。 '$ variable 'を'% 'の間の文字列に設定した後、' $ ENV {$ variable} 'を使って環境変数を取得できます。 – Barmar

答えて

0

あなたはこの

awk '{gsub(/%user_home%/,"${user_home}")}1' file 
NameVirtualHost *:80 

<VirtualHost *:80> 
    ServerName %server_name% 

    ErrorLog /var/log/apache2/${user_home}_webapp_error.log 
    CustomLog /var/log/apache2/${user_home}_webapp.log common 

    DocumentRoot /home/${user_home}/web_app/public 
</VirtualHost> 

を行うことができますawkを使用してこれは変数${user_home}

3

%user_home%を置き換えるここでの問題は、時間によってsedコマンドが実際にそれを実行します(そのための時間であるということです変数名を取得する場合)、sedコマンドが完全にアセンブルされている必要があります(置換文字列にBash変数の値を代入するなど)。すべてが間違った順序で起こります。

sedは、より高いレベルのビューを使用しているため、変数の詳細を提供するためにBashが必要ですが、Bashはsedの置換えを知らないため、あなたが必要とする変数を知る方法はありません。

Bash変数を使用したい場合は、最初にsedを呼び出す前に関連する変数名を特定する必要があります。あなたがそれを行う方法を以下に示します。 。

grep -o '%[a-z_][a-z_]*%' FILE | grep -o '[a-z_][a-z_]*' | sort -u 

(最初grepフォーム%...%のすべての式を取得する第二grepフィルタ:


は、あなたがこのような何かを書くことができ、ファイル内のすべての変数、名前のリストを取得するにはあなたが好きな場合は、 sedを使用することができます。 の別名という変数名のリストのみが必要なので、 sort -uは重複を排除します。)

それを武器に、あなたが必要なすべての置換を行いsedコマンド組み立てることができます。

sed_args=() 
while read varname ; do 
    sed_args+=(-e "s/%$varname%/${!varname}/g") 
done < <(grep -o '%[a-z_][a-z_]*%' FILE | grep -o '[a-z_][a-z_]*' | sort -u) 
sed "${sed_args[@]}" FILE 

を(変数名として$varnameの値をとる」ことを意味する${!varname}の使用に注意してください、とその変数の値を返す間接的拡大 『「これは§3.5.3 "Shell Parameter Expansion" of the Bash Reference Manualが呼ぶものである』)

あなたが機能でこれをラップすることができます:。。

function replace_bash_variables() { 
    local file="$1" 
    local sed_args=() 
    local varname 
    while read varname ; do 
     sed_args+=(-e "s/%$varname%/${!varname}/g") 
    done < <(grep -o '%[a-z_][a-z_]*%' "$file" | grep -o '[a-z_][a-z_]*' | sort -u) 
    if [[ "${#sed_args[@]}" = 0 ]] ; then 
     # if no variables to replace, just cat the file: 
     cat -- "$file" 
    else 
     sed "${sed_args[@]}" -- "$file" 
    fi 
} 

replace_bash_variables OLD_FILE > NEW_FILE 

上記を調整して、ファイルを2回読み取る必要がないように、行単位で処理することもできます。 (ファイルの読み取りが二回あなたが実際のファイルに渡すために持っていることを意味し、(例えば)パイプラインの出力にこれを適用することはできませんので、それは、あなたに多くの柔軟性を提供します。)

+0

これはすばらしい解決策であり、問​​題を解決しますが、そのまま動作させることはできません。 grepの出力を一時ファイルにリダイレクトしてから、そのファイルをwhileループにリダイレクトするだけで、動作させることができます。 上記のコードを実行すると、予期しないトークン '{ ] [a-z _] * '| sort -u)'となります。 – richard

+0

@reagleton:申し訳ありませんが、愚かな間違いです。私の[プロセス置換](http://www.gnu.org/software/bash/manual/bashref.html#Process-Substitution)については、私が '<< (...) '。 (私はこの誤りを恥ずかしく思っています。<(...) 'それは標準入力をリダイレクトしているように見えますが、FIFOやその他の名前の名前に置き換えられません。 – ruakh

0

を使用し、この:

sed -E "s/%(\w+)%/\$\1/g" 

たとえば、この:

echo "abcdef %variable% blah" | sed -E "s/%(\w+)%/\$\1/g" 

プリント:

abcdef $variable blah 
0

は1 SEDと試みるが、それでもトン以前に必要Oによる文字の使用に

#!/bin/ksh 
# YourFilename contain the file name of your file to treat (here passed as 1st parameter to a script) 
YourFileName=$1 

(set | sed 's/.*/#V0r:&:r0V#/'; cat ${YourFileName}) | sed -n " 
s/$/²/ 
H 

$ { 
    x 
    s/^\(\n *\)*// 
# also reset t flag 
    t varxs 

:varxs 
    s/^#V0r:\([a-zA-Z0-9_]\{1,\}\)=\([^²]*\):r0V#²\(\n.*\)%\1%/#V0r:\1=\2:r0V#²\3\2/ 
    t varxs 
: tmpb 

# clean the line when no more occurance in text 
# s/^#V0r:\([a-zA-Z0-9_]\{1,\}\)=\([^²]*\):r0V#²\n// 
    s/^[^²]*:r0V#²\n// 

# and next 
    t varxs 


# clean the marker 
    s/²\(\n\)/\1/g 
    s/²$// 

# display the result 
    p 
    } 
" 
  • 制限ここでは、変数名と値を知っているコンテンツ「セット」キャッチ「²」²がファイルに表示されますので、もしエスケープない、いらいらすることができた(ので、これを変更しますマーカーとしてcharまたはファイルにそれを翻訳)
  • #V0r:と:r0V#がまた、マーカーであり、
関連する問題