0

sedと一重引用符に問題があります

私はこのような文字列を持っています:

-cmd af -i 3 -a

この文字列をに変更したい

-cmd 'af -i 3 -a'

今私はこれを使用しています:

文字列はbuff変数に格納されます

buff=$(echo $buff | sed -r "s/cmd /CMD '/g")"'"

それは大丈夫エコーします -cmd 'af -i 3 -a'

次に、buffをパラメーターとして関数を呼び出し、ksh -xを使用してスクリプトを実行しているときに、呼び出しがNOKであることがわかります。

+ buff=$'-CMD \'af -i 3 -a \''
+ echo -CMD $'\'af' -i 3 -a $'\''
-CMD 'af -i 3 -a' #this is the echo
+ functionTest -CMD $'\'af' -i 3 -a $'\''

結果として、それは常に私に与えます

-CMD $'\'af' -i 3 -a $'\''

つまり、基本的に、私の単一引用符は次のように解釈されるようです。$'\''

理由はわかりません。文字をエスケープするなど、さまざまなことを試しましたが、まったく同じ結果が得られます。\x27

4

3 に答える 3

2

奇妙な結果をどのように見ていますか?

あなたが持っているものは生でOKです(sedMac OS Xではサポート-rされていませんが、使用される正規表現はとにかく非標準のGNU拡張オプションを必要としませ-rん):

$ buff1="-cmd af -i 3 -a"
$ buff2=$(echo $buff1 | sed -e "s/cmd /CMD '/g")"'"
$ echo $buff2
-CMD 'af -i 3 -a'
$

あなたの問題は変換ではなく、結果の表示方法にあると思います。


kshテスト

Osiris JL: cat so14043243.sh
buff1="-cmd af -i 3 -a"
buff2=$(echo $buff1 | sed -e "s/cmd /CMD '/g")"'"
echo $buff2
echo "$buff2"
Osiris JL: ksh -x so14043243.sh
+ buff1='-cmd af -i 3 -a'
+ sed -e $'s/cmd /CMD \'/g'
+ echo -cmd af -i 3 -a
+ buff2=$'-CMD \'af -i 3 -a\''
+ echo -CMD $'\'af' -i 3 $'-a\''
-CMD 'af -i 3 -a'
+ echo $'-CMD \'af -i 3 -a\''
-CMD 'af -i 3 -a'
Osiris JL: 

出力は正しいです。トレースは少し紛らわしいですが、あなたが示しているものと同じです。

-x出力に余分な労力を費やすのには十分な理由があります。それはあなたがそれを十分に読むことができればあなたが何が何であるかを正確に決定することができるように出力を明確にします。また、'n'の後に行をコピーして貼り付けて+実行すると、まったく同じ結果が得られます。古いBourneシェルには、-xこのような文字マッピングを行わないオプションがあり、混乱を招く可能性があり、トレース出力を確実にコピーして貼り付けてコマンドを再実行することはできませんでした。

重要な点は、結果(エコーされるもの)があなたが望むものであり、期待するものであるため、(それが起こったときに)何も心配していないということです。しかし、私は同意します、それは最初は混乱する可能性があります。

于 2012-12-26T16:29:57.783 に答える
2

それは私にとってもうまくいきます。しかし、必要はありませんsed; bashビルトインはこれをうまく行うことができます:

$ buff='-cmd af -i 3 -a'
$ buff=${buff/cmd /CMD \'}\'
$ echo $buff
-CMD 'af -i 3 -a'
于 2012-12-26T16:32:51.773 に答える
0

文字列を変数に格納することについての@gniourf_gniourfの最初のコメントは、基本的に正しいと思います(コマンド引数を格納しようとしているだけですが)。BashFAQ#050を参照してください:コマンドを変数に入れようとしていますが、複雑なケースは常に失敗します!

ここで、2つの混乱があります。1つ目は、どの-xモードが印刷されているかを誤解していることです。実行しているコマンドの引数は出力されません。同じ引数を渡すコマンドが出力されます。この場合、一部の引数には一重引用符が含まれているため、引用符とエスケープされた文字列が返され、引用符を削除すると、実際に渡されるのと同じ引数になります。たとえば、引数の1つは。'afであるため、-xモードではそれが。として表示され$'\'af'ます。

次に、変数に一重引用符を埋め込もうとしているようです。これにより、複数の単語を単一の引数としてfunctionTestに渡すことができます(つまり、functionTest -CMD 'af -i 3 -a'). If I'm right about what you're trying to do, you're doing it fundamentally wrong. When the shell parses a command line, it interprets quotes and escapes, *then* substitutes variables. It'll go back and split the replaced variables into words, but it will not go back and pay attention to quotes and escapes in the substituted text. So when it replaces$ buff with-CMD'af-iと同等のものを実行しようとしています。 3 -a'`は、これを5つの引数「-CMD」、「af」、「-i」、「3」、および「-a」に分割します。一重引用符は、 2番目と5番目の引数。単一の長い引数を囲むものではありません。

$ buff="-CMD 'af -i 3 -a'"
$ printargs $buff
Got 5 arguments:
  «-CMD»
  «'af»
  «-i»
  «3»
  «-a'»

この種の混乱なしに複数の引数を格納するには、配列を使用する必要があります(ここでも、@ gniourf_gniourfのコメントとBashFAQ#050を参照してください)。

$ buff=(-CMD 'af -i 3 -a')
$ printargs "${buff[@]}"
Got 2 arguments:
  «-CMD»
  «af -i 3 -a»

ところで、これを複製しようとしている場合は、printargsが必要になります。これは、次のような状況を明確にするために作成した非常に単純なシェルスクリプトです。

#!/bin/sh

echo "Got $# arguments:"
for arg; do
        echo "  «${arg}»"
done
于 2012-12-26T18:59:02.490 に答える