Bashで引用符付き文字列内の環境変数を使用する方法


91

私はbashスクリプトで以下のさまざまな形式を試しました:

#!/bin/bash
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

しかし、COLUMNS環境変数を正しく展開するための構文を取得できません。

私は以下のさまざまな形を試しました:

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W $COLUMNS'

そして

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W ${COLUMNS}'

そして

eval svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

提案?


あなたの場合、それらの例は何を生み出すのでしょうか?そして、あなたは彼らに何を生み出して欲しいのですか?

スクリプト外のコマンドは機能していますか?
dfa 2009年

お試しになりましたかsvn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W ""$COLUMNS"
Qian Chen

ところで、unquotedを使用$@すると、完全に同じになります$*-つまり、"foo bar"2つの別々の引数に分割されます。fooとしbar。与えられたとおりに元の引数リストを保持したい場合は、が必要です"$@"
Charles Duffy

回答:


16

不明な場合は、ターミナルで 'cols'リクエストを使用し、COLUMNSを忘れる可能性があります。

COLS=$(tput cols)

理由が何であれ、これは私がこのページから作業を始めることができた唯一の解決策です(11月5日10:38 ET現在)。ありがとう
ジェイミー

397

(私がそうであったように)タイトルで尋ねられた一般的な質問への回答を探しているグーグル経由でここに来た人のためのちょうど簡単なメモ/要約。引用符内のシェル変数にアクセスするには、次のいずれかが機能します。

echo "$VARIABLE"
echo "${VARIABLE}"

単一引用符の使用が主な問題です。Bashリファレンスマニュアルによると

文字を単一引用符(')で囲むと、引用符内の各文字のリテラル値が保持されます。バックスラッシュが前に付いていても、一重引用符は一重引用符の間に出現しない場合があります。[...]二重引用符で囲み文字(")を除いて、全ての文字のリテラル値を保持し$`\、および、履歴展開が有効になっている場合、!。文字$と `は、二重引用符内で特別な意味を保持します(シェル展開を参照)。バックスラッシュは、次のいずれかの文字が続くだけの特別な意味を保持:$`"\、または改行。二重引用符内では、これらの文字のいずれかが後に続くバックスラッシュが削除されます。特別な意味のない文字の前のバックスラッシュは変更されません。二重引用符は、バックスラッシュを前に付けることにより、二重引用符で囲むことができます。有効に!すると、二重引用符で囲まれた箇所がバックスラッシュを使用してエスケープされない限り、履歴の展開が実行されます。の前のバックスラッシュ!は削除されません。特別なパラメーターは、二重引用符で囲まれたときに特別な意味*@持ちます(シェルパラメーターの展開を参照)。

質問で尋ねられた特定のケースでは、$ COLUMNSは非標準のプロパティを持つ特別な変数です(上記のlhunathの回答を参照)。


20
単一引用符の場合、この回避策が役立つかもしれません:( 'before'"$variable"'after'この回答で述べたように:stackoverflow.com/a/13802438/2254346
MakisH

正解です。単一引用符内で環境変数を参照するという同じ問題がありました。一重引用符を二重引用符に変更すると、期待どおりに環境変数が拡張されていました。
Binita Bharati

14

次のことに注意してくださいCOLUMNS

  1. ない環境変数ではあり。これは、bash自体によって設定される通常のbashパラメータです。
  2. SIGWINCH信号を受信すると自動的に設定されます。

その第二の点は、通常、あなたのことを意味COLUMNS変数は、あなたの中に設定されます、対話型シェル、ない bashスクリプトで。

スクリプトstdinが端末に接続されている場合は、端末に問い合わせることで手動で端末の幅を調べることができます。

tput cols

これをSVNコマンドで使用するには:

svn diff "$@" --diff-cmd /usr/bin/diff -x "-y -w -p -W $(tput cols)"

(注:引用 "$@"してeval;-)に近づかないでください))


情報のおかげで; 何が起こっているのかを知ることは、問題にカタルシスの感覚をもたらします。
ジェイミー、

2

次のスクリプトは、の複数の値に対して機能します$COLUMNS。あなたはCOLUMNSこの電話の前に設定していないのだろうか?

#!/bin/bash
COLUMNS=30
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

$COLUMNSスクリプト内をエコーして、正しく設定されているかどうかを確認できますか?


ブー、ヒス再:引用符で囲まれていない$@-単一のパラメータを分割"two words"二つの別々のパラメータにアップし、twoそしてwords"$@"与えられたとおりに引数リストを渡す必要があります。
チャールズダフィー

0

あなたはそれを正しくやっているので、私は他に何か問題があると思います(COLUMNSをエクスポートしていないのですか?)。

これらのケースをデバッグするための秘訣は、特殊なコマンド(プログラミング言語の人のためのクロージャー)を作成することです。diff-columnsという名前のシェルスクリプトを作成します。

exec /usr/bin/diff -x -y -w -p -W "$COLUMNS" "$@"

そしてただ使う

svn diff "$@" --diff-cmd  diff-columns

このようにして、コードは読みやすくなり、よりモジュール化され(トップダウンアプローチ)、diff-columnsコードを個別に完全にテストできます(ボトムアップアプローチ)。


コマンドラインはプロセスが分岐する前に解析されるため、COLUMNSをエクスポートしないことは問題にはなりません。
Peter van der Heijden、

1
彼のコードはbashスクリプトの一部であるため、問題になる可能性があります。
Colas Nahaboo、2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.