web-dev-qa-db-ja.com

Bashの変数置換でのバックスラッシュ

ハードドライブを正しくパーティション分割するためにBashスクリプトを作成していたところ、変数に数値を追加しなければならないという奇妙な問題に遭遇しました。私はBashの経験があまりないので、正しい結果が出るまで少し時間がかかりましたが、なんとか一時的なものを作ることができました。

これが私が作ったものの例です:

#!/bin/bash

devName="/dev/sda"
devTarget=$devName\3

echo "$devTarget"

変数devName/dev/sdaですが、後のスクリプトで3番目のパーティションの変数セットも必要なので、\記号。数字を追加します3から/dev/sda出力を作成する/dev/sda3

\シンボルが機能しました。これがこのようなことを行う正しい方法であるかどうか疑問に思っていました。 Pythonでは引用符などで次の文字を無視するために使用されているため、これを使用しましたが、この状況では反対のことをしたかったので、驚くほどうまくいきました。これが最善ではない場合変数に追加する方法について、誰かがBashでこれを行うための最良の方法の例を示してください。

4
user270900

変数を文字列に補間する安全な方法は、${var_name}を使用することです。例えば:

#!/bin/bash

devName="/dev/sda"
devTarget="${devName}3"

echo "$devTarget"

このようにして、Bashは補間する変数が何であるかについて疑いを持ちません。

ところで、devTarget=$devName\3の仕組みは興味深いです。理由はわかりません。

8
user147505

$x\b$x"b"または"$x"bと同じように機能し、引用符は変数名を終了します。他に理由がない場合、これは変数が展開されたときに引用符がまだあり、変数名で\"'がどれも有効でないために発生すると思います。

標準テキスト はそれを言います:

Word展開の順序は次のとおりです。

1. ...、パラメーター展開(パラメーター展開を参照)、...

4.引用の削除(引用の削除を参照)は常に最後に実行する必要があります。

そして、「引用の削除」は実際に引用文字を削除するステップです。

しかし、@ tomaszが回答 で述べたように 、変数名を中括弧で囲むことが通常の方法なので、"${x}b"、または"${devName}3"。たいていの場合、展開を引用符で囲みます。 を参照してください。二重引用符が必要になるのはいつですか?

(ただし、プログラム内で引用符付き文字列をマークする方法として、引用符文字を実際に残しておく以外に他の方法があるのではないかと思いました。)

5
ilkkachu

スクリプトが示すのは、変数と数値を出力に書き込んでいることです。 printfとフォーマットされた文字列で達成できるほど簡単です:

$ devName="/dev/sda"
$ printf "%s%d\n" "$devName" 3
/dev/sda3

ただし、スクリプトの後半で新しい変数をuseする必要があると述べたように、bashのバージョンで-vフラグを使用することもできます。 of printf

$ printf -v devTarget "%s%d" "$devName" 3
$ echo "$devTarget"
/dev/sda3

このアプローチは [〜#〜] posix [〜#〜] printfでは機能せず、他のシェルでは機能しません(少なくともkshとmkshには-vがありません) printfのフラグ、zhshについては不明)。したがって、コマンド置換を介してこれを回避できます。

$ devTarget=$(printf "%s3" "$devName")

ただし、 受け入れられた答え はおそらくより単純で移植性が高いでしょう。

3

tomaszが指摘 のように、変数名を構成する文字を正確に指定する適切な方法は、${devName}3のように中括弧を使用することです。

Bashでは、便宜上中括弧を省略できますが、その場合、参照する変数を完全に明示することができなくなります。 bashがこれを解決する方法は、ドル記号の後に始まる可能な限り長い有効な変数名を取ることです。変数名は、文字またはアンダースコアで始まり、任意の数の文字、数字、またはアンダースコアを含むことができますが、他の文字を含めることはできません。したがって、あなたの例では、$devName\3、bashはdで始まり、見つけることができる文字/数字/アンダースコア文字の最長の連続、つまりdevNameを探します。それを使用する変数の名前にする必要があります。同様に、$here-is-a-long-string-of-wordsのようなものは、hereという名前の変数を使用します。 ${here}-is-a-long-string-of-wordsのようになります。

その後、bashは\3を参照します。バックスラッシュは、後続の文字を特別な意味なしに通常どおりに解釈させるという意味で、引用の形式です。ただし、3には特別な意味がないため、バックスラッシュは冗長です。このシーケンスは、それだけで3と等価になるまで巻き上げられます。

1
David Z