単一引用符内で変数を使用する方法


11

一重引用符に埋め込まれた二重引用符で属性を入力として受け取るアプリケーションがあります。たとえば、次の正しいコマンドを見てください。

command -p 'cluster="cl1"'

それを自動化するために$CLUSTER、変数としてを使用してbashファイルを作成しました。私の命令はどうあるべきですか?つまり、cl1の代わりに何を配置すればよいですか。

上記のコマンドを変更すると、受け入れられなくなりますのでご注意ください。たとえば:command -p "cluster=cl1"受け入れられません


2
CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"
mikeserv 2015年

別の可能性(変数cli内に引用符なしで保存したい場合CLUSTER):CLUSTER='cl1'; command -p 'cluster="'"$CLUSTER"'"'
jimmij

最後に、私は正しい答えを見つけました。@jimmijに感謝します。
Mohamad-Jaafar NEHME、2015年

回答:


8

コマンドがコマンドラインで指定された引数に基づいて環境変数を設定している可能性があります。それはあなたができるかもしれません:

CLUSTER=cl1; cluster=$CLUSTER command

...呼び出し時にその環境を設定します。

それ以外の場合、通常、シェルの引用符は引数を区切るか、他の特殊なシェル文字をシェルの解釈からエスケープします。さまざまな規則に基づいて、他の種類の中に異なる種類のシェル引用符を含める(したがってエスケープする)ことができます。

  • "''''" -ソフトクォートされた文字列には、ハードクォートをいくつでも含めることができます。
  • "\""- \バックスラッシュは、"ソフトクォート"された文字列内のソフトクォートをエスケープできます。
    • このコンテキストでは、\\バックスラッシュも以下に示すように、それ自体、\$展開トークン、および\newlinesをエスケープしますが、それ以外の場合は文字どおりに扱われます。
  • "${expand} and then some"-ソフトクォートされた文字列は解釈されたシェル$展開を含むことができます。
  • '"\'- 'ハード'クォートされた文字列には、ハードクォート以外の文字を含めることができます。
  • \-引用符で囲まれていないバックスラッシュは、文字どおり解釈するために後続の文字をエスケープします-もう1つのバックスラッシュでさえ\n-ewline を除きます。
    • \\newlineケースの両方\バックスラッシュと\newline完全得解釈コマンドから除去されます。
  • ${parameter+expand "$parameter"}-いくつかの特別な場合を除いて、シェル展開から得られる引用符が区切り記号として機能することはほとんどありません。ここでは、これらについてさらに説明するつもりはありません。

どのアプリケーションもコマンドライン引数の引用符を解釈するのは奇妙だと思います。そのような慣行は、シェルでは少なくとも意味がありません。少なくとも、引用符の主な目的は、一般的に引数を区切ることです。ただし、呼び出し時には、引数は常に文字区切られ\0NULいるため、引用符はあまり目的に使用できません。

シェルであっても、-cスイッチで呼び出された場合、通常、呼び出し引数の1つで引用符を解釈するだけで済みます。これは、最初のオペランドが実際に呼び出し時に実行するシェルスクリプトであることを示します。これは、2回評価された入力の場合です。

そうは言っても、コマンドラインの引数を介してリテラル引用符を渡すために多くのことを行うことができます。例えば:

CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"

以前のコメントで述べたように、"それ自体が"引用されている展開内に引用符を含めることができます。

CLUSTER=cl1; command -p "cluster=\"$CLUSTER\""

引用符で囲まれた文字列内でバックスラッシュを使用"して\エスケープでき"ます。

CLUSTER=cl1; command -p cluster='"'"$CLUSTER"'"'

上記の @jimmijの注記のように、希望する最終結果に到達するために、引用スタイルを交互に連結することができます。

CLUSTER=cl1; ( set -f; IFS=; command -p cluster=\"$CLUSTER\" )

ファイル名の生成$IFS分割の両方を無効にして、引用符$expansionをまったく引用する必要をなくし、引用符だけを引用することができます。これはおそらくやり過ぎです。

最後に、使用できる別のタイプのシェル引用があります。前述のように、sh -c "$scriptlet"シェル呼び出しの形式は、コマンドラインでシェルのスクリプトを提供するためによく使用されます。$scriptletただし、引用符が他の引用符を含む必要がある場合など、複雑になる場合は、ヒアドキュメントを使用する方が有利な場合が多く、sh -s代わりに、ケースのように、次のすべてのオペランドを位置パラメータに割り当てるようにシェルに具体的に指示します。-cまた、そのスクリプトもから取得しますstdin

コマンドがこのように引用符を解釈する必要がある場合は、ファイル入力で解釈できればより良いと考えます。例えば:

CLUSTER=cl1
command --stdin <<-SCRIPT
    cluster="$CLUSTER"
SCRIPT

の区切り文字を引用符で囲まないと、<<here-documentそのすべての内容は、"ソフトクォートされたのとほぼ同じように扱われます。ただし"二重引用符自体は特別に扱われません。そして、cat代わりに上記を実行すると:

CLUSTER=cl1
cat <<-SCRIPT
        cluster="$CLUSTER"
SCRIPT

...印刷します...

cluster="cl1"

1

同様mikeservは書きました:

 CLUSTER='"cl1"'; command -p "cluster=$CLUSTER" 

「二重引用符」スペース/メタ文字を含むすべてのリテラルと、すべての拡張:"$var""$(command "$var")""${array[@]}""a & b"。使用する'single quotes'コードまたはリテラルのために$'s: 'Costs $5 US'ssh host 'echo "$HOSTNAME"'。参照してください
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words


あなたは正しいです、ありがとう。しかし、自動化はどうですか?CLUSTERを読みたいと思いますか?同じ問題で再び行き詰まります。単一引用符内の変数
Mohamad-Jaafar NEHME、2015年

@Moi-自動化は大したことではありませんが、"文字の変数をサニタイズする必要があります-最初と最後だけで十分です。ここでの実際の問題は、アプリが引数の引用符を解釈することです。引用符は引数を区切る手段に過ぎないため、引数の引用符を解釈することはほとんど決して良い考えではありません。起動時には、区切り文字は\0NULすべてs によって処理されます。おそらく、アプリに必要な情報を渡すためのより良い方法がありますか?Aのようなcommand --'script=/path/to/some/file'か何か?
mikeserv 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.