2011-12-07 6 views
2

私は、文字列から先頭のタブ/スペースを除去することになっている短いbashスクリプトを書いた:バッシュの引用の挙動とSEDが

#!/bin/bash 
RGX='s/^[ \t]*//' 
SED="sed '$RGX'" 
echo "  string" | $SED 

それは、コマンドラインから動作しますが、スクリプトはこのエラーを取得します。

sed: -e expression #1, char 1: unknown command: `'' 

私の推測では、引用符に何か問題がありますが、わかりません。

答えて

4

です。試してください:

#!/bin/bash 
RGX='s/^[ \t]*//' 
#SED='$RGX' 
echo "  string" | sed "$RGX" 

これは動作します。

問題は、引用符とスペースです。二重引用符で囲まれた文字列は単一の引数として渡されます。これはまた、特別な理由のために、あなたの正規表現の拡張ひとつとなっていることを

#!/bin/bash 
RGX='s/^[[:space:]]+//' 
SED="sed -r '$RGX'" 
eval "printf \" \tstring\n\" | $SED" 

注:上記の私のコメントに拡大すること

+0

これは受け入れられますが、sedコマンドとRGXを1つの文字列にまとめることは可能ですか? – krs1

+0

@ krs1、この場合、実際はありません。 '$ RGX'が1つの引数として残るようにする必要があります(そのスペースが2に解釈されることはありません)が、パイプの後に' sed'と '$ RGX'の間にスペースが必要ですあなたが 'sed $ RGX'という名前のプログラムではなく' sed'に文字列をパイプすることを試みていることを知ってください。 – jedwards

+0

実際には、変数を展開する前に変数を展開する 'eval'を使って行を実行すると、それらをまとめてまとめることができます。詳細については 'man bash'と" eval "(" SHELL BUILTIN COMMANDS "のマンページの正しい場所に前後にスペースを入れて検索)を検索してください。 – ghoti

3

set -xをスクリプトに追加します。一重引用符内の変数は展開されていないことがわかります。

3

引用符が期待どおりに機能しないため、コマンドを変数に入れて元に戻すのは難しいです(BashFAQ #050, "I'm trying to put a command in a variable, but the complex cases always fail!"参照)。これに対処するにはいくつかの方法があります:

1)本当に必要な場合以外は、実行しないでください。真剣に、あなたが最初に変数にあなたのコマンドを置く正当な理由がなければ、それを実行し、この厄介さに対処しないでください。

2)は本当に本当にに必要なあなたは本当にない限りevalを使用しないでください。 evalは、厄介で不明瞭なバグの原因として十分な評価を得ています。それらを十分に理解し、それを避けるために必要な予防措置を講じるなら、避けることができますが、これは本当に最後の手段になるはずです。

3)コマンドをある時点で定義して後で使用する必要がある場合は、それを関数または配列として定義する必要があります。ここでは機能でそれを行う方法は次のとおりです。

RGX='s/^[ \t]*//' 
SEDCMD() { sed "$RGX"; } 
echo "  string" | SEDCMD 

ここで配列バージョンです:

RGX='s/^[ \t]*//' 
SEDCMD=(sed "$RGX") 
echo "  string" | "${SEDCMD[@]}" 

イディオム"${SEDCMD[@]}"は、あなたが問題あなたのいずれかのなしに、各要素に別々の単語を保ち、アレイを拡張することができます持っている。

+0

良い点として、引用符はbashスクリプトでファンキーです。私はPythonの引用符に慣れています。 – krs1