一部のパラメータが変数から来た場合、コマンド置換がどのように機能するかを理解できません。
これを説明するために一連のコマンドを提供します。
まずA B C
、tmpディレクトリ内にディレクトリを作成し、新しいディレクトリに新しいファイルを作成しますabcfile
。
user@desktop /tmp
$ pwd
/tmp
user@desktop /tmp
$ mkdir "A B C"
user@desktop /tmp
$ ls
'A B C'
user@desktop /tmp
$ touch "A B C"/abcfile
user@desktop /tmp
$ ls "A B C"/
abcfile
A B C
変数に新しい値を代入し、ディレクトリの内容を一覧表示するコマンドを呼び出すさまざまな方法を$DIR
試してみましょう。ls
user@desktop /tmp
$ DIR="A B C"
変数が引用されない場合、コマンドは期待どおりに失敗します。
user@desktop /tmp
$ ls $DIR
ls: cannot access 'A': No such file or directory
ls: cannot access 'B': No such file or directory
ls: cannot access 'C': No such file or directory
変数を参照した後、期待どおりに動作します。
user@desktop /tmp
$ ls "$DIR"
abcfile
コマンドの出力を文字列にしたい場合
user@desktop /tmp
$ echo $(ls "$DIR")
abcfile
このコマンドは動作しますが、なぜ動作しますか? Shellcheckによると、これは実際には正しくありません。変数は二重引用符の外になければなりません。
user@desktop /tmp
$ echo "$(ls "$DIR")"
abcfile
内部変数に二重引用符がないと、コマンドは失敗します。
user@desktop /tmp
$ echo "$(ls $DIR)"
ls: cannot access 'A': No such file or directory
ls: cannot access 'B': No such file or directory
ls: cannot access 'C': No such file or directory
答え1
私は出力コマンドの出力をecho "$(somecommand)"
asに置き換える必要はなく、この構成を単に例として使用していることを知っているとします。somecommand
echo
出力が印刷されるため、コマンドはecho $(ls "$DIR")
「動作」します。ls "$DIR"
abcfile
echo
この場合、ここでコマンドの置き換えを引用しても効果はありません。ファイル名の文字を含むように文字列を変更しない限り、文字列にはabcfile
引用符は必要ありません(下記の理由を参照)。$IFS
ただし、次の点を考慮してください。
A B C/
|-- A*
`-- abcfile
今:
$ echo "$(ls "$DIR")"
A*
abcfile
$ echo $(ls "$DIR")
A B C abcfile
最後の出力では、ファイル名をA*
ディレクトリ名と一致するファイル名ワイルドカードパターンに拡張しますA B C
。また、出力で改行文字が失われたことがわかりますls
。
シェルが失われるため、改行文字が失われます。噴射引用符のない出力では、ls
スペース、タブ、および改行(のデフォルト$IFS
)を使用して単語に分割します。
ディレクトリ名には、A B C
単語分割によって生成された単語が含まれているため挿入されます。ファイル名の生成(ワイルドカード)。
新しいファイル名がある場合は、A* A*
ディレクトリ名が2回挿入されます。
A B C/
|-- A* A*
`-- abcfile
$ echo $(ls "$DIR")
A B C A B C abcfile
関連:
答え2
これが主な誤解のようです。
変数は二重引用符の外になければなりません。
user@desktop /tmp $ echo "$(ls "$DIR")" abcfile
変数は二重引用符しかありません。シェルは内部で引用を検討します。$()
それぞれ外部から引用するよりも。つまり、echo "$(ls "$DIR")"
二重引用符の中には実際に入れ子になった:
echo "$(ls "$DIR")"
# ^ ^ inner quotes
# ^ ^ outer quotes
一般的に二重引用符で囲まれた変数は良いのでそして明細書$()
全体にこれらの引用符がそれぞれ必要です(引用したくない場合を除く)。
「クイック2」の比較この回答。
追加の質問:
コマンドの出力を文字列にしたい場合
user@desktop /tmp $ echo $(ls "$DIR") abcfile
stdoutの出力には型がなく、echo
文字列にはなりません。この特別なケースではecho
何も変わりませんが、以下を参照してください。何が間違っていますかecho $(stuff)
?