web-dev-qa-db-ja.com

一重引用符やその他の特殊文字を含む文字列を印刷します

これをAIXスクリプトで正しく記述するにはどうすればよいですか?私の要件は、このコマンドをtest.txtに記述することです。

clock=$(prtconf -s | awk '{print $4,$5}')

私はこのコマンドを試しました:

print 'clock=$(prtconf -s | awk '{print $4,$5}')' > test.txt

Test.txtに書かれた出力は私に与えます:

clock=$(prtconf -s | awk {print ,})

" "の引用符を使用する場合:

print "clock=$(prtconf -s | awk '{print $4,$5}')"

それは私に直接与えます:

clock=3612 MHz

どうすればこれを解決できますか?

8
batil

一重引用符を使用し続けながら、必要なものを「個別に」出力に出力するか、二重引用符を使用してドル記号をエスケープする必要があります。

2番目のオプションの場合:

print "clock=\$(prtconf -s | awk '{print \$4,\$5}')" > test.txt

最初に:

print 'clock=$(prtconf -s | awk '\''{print $4,$5}'\'')' > test.txt

(それは'text'は単一引用符をエスケープしました\'、次に'other text'。)

完全を期すために、printはバックスラッシュ文字のエスケープシーケンスを展開することに注意してください(印刷する文字列にはバックスラッシュが含まれていないため、これは問題ではありません)。これを回避するには、print -r

4
Mat

これを行う簡単な方法は、文字列を単一引用符'…'で囲むことです。単一引用符はリテラル文字列を区切るため、単一引用符'を除いて、それらの間に何でも置くことができます。文字列に単一引用符を挿入するには、4文字のシーケンス'\''(単一引用符、バックスラッシュ、単一引用符、単一引用符)を使用します。

技術的には、単一引用符で囲まれたリテラル内に単一引用符を配置する方法はありません。ただし、連続するリテラルは単一のリテラルと同じくらい優れています。 'foo'\''bar'は次のように解析されます

  1. 一重引用符付きのリテラルfoo
  2. バックスラッシュで引用されたリテラル文字'
  3. 一重引用符付きのリテラルbar

これは事実上、'\''が単一引用符で囲まれたリテラルの単一引用符をエスケープする方法であることを意味します。

Ksh printコマンドはバックスラッシュ展開を実行することに注意してください。これを回避するには、-rオプションを追加します。印刷したい文字列にはバックスラッシュがないので害はありませんが、メンテナンス中にバックスラッシュが追加される場合に備えて、-rを使用することをお勧めします。

print -r -- 'clock=$(prtconf -s | awk '\''{print $4,$5}'\'')' > test.txt

または、POSIXメソッドを使用して、文字列の最後に改行を付けて文字列を出力することもできます。

printf '%s\n' 'clock=$(prtconf -s | awk '\''{print $4,$5}'\'')' > test.txt

@Matが言ったように2つの解決策があります。

1]単一引用符'の使用:この単一引用符は、さまざまなコマンド(基本的にすべてのbash構文とUNIXコマンド)のエスケープ文字$の特別な意味を取り除きます。 printコマンドはすべてをプレーン文字として受け取り、これをファイルtest.txtに書き込みます

2]二重引用符の使用":ここでは、bash構文を明示的にエスケープする必要があります。 \$は、$の特別な意味、つまり$の後に使用される変数の値を削除します。

1
Tingrammer

ここにドキュメント を使用しないのはなぜですか?

_cat <<'END' > test.txt
clock=$(prtconf -s | awk '{print $4,$5}')
END
_

_<<'END'_のENDを囲む引用符に注意してください。これらは、次の行のテキストが(ENDマーカーまで)文字どおりに使用されることを意味します。 _<<END_だけで、ドル拡張(つまり、$(command)または_$variable_)が実行されます。

1
Joseph R.