シェル(zsh / bash)での拡張と引用をよく理解していません。

シェル(zsh / bash)での拡張と引用をよく理解していません。

シェルから変数を引用するための答えをここで読みました。基本的にこれは私が実行するものです。

for f in "$(tmsu files)"; do echo "${f}"; done

これは予想される結果です:ファイルのリスト。しかし、私はそれらが1つの文字列として現れると確信しています。少し読んだ後、これがzsh-ismであることに気づきました。これは、ほとんどのシェルとは異なる方法で分割を処理します。

bashだから私は同じコマンドを実行して実行しました。リストが分割されると思いましたが、残念ながら正確に同じ結果。だから今は本当に混乱しています。

  1. Bashが期待どおりに実行されないのはなぜですか?
  2. zsh分割線を作成する方法は?

私は(zsh)を試しましたが成功しなかったfor f in "$(tmsu files)"; do echo "${=f}"; done ので for f in "$(=tmsu files)"; do echo "${f}"; done 、分割方法を誤解したようですzsh

さらに悪いことは、ある時点で私が望むように正確に動作するようにしましたが、どうしたのか覚えていないということです。

ベストアンサー1

for f in "$(tmsu files)"; do echo "${f}"; done

これはzsh-ismよりも悪い習慣です。二重引用符は、拡張結果を単一の文字列として保持するようにシェルに指示します。ほとんどの場合、これはあなたが望むものです。たとえば、次のような場合があります。

filename="foo bar"
ls "$filename"

2つの引数lsの合計ではなく単一の引数でファイル名を取得しようとしています。 (これらは別のファイル名になります。)これで、コマンド置換を使用しているという事実はこれを変更しません。この場合、引用が問題を解決できないことは正しいですが、この構成は最初は厄介です。 (もちろん、POSIXシェルにはzshに独自のツールがあります)。foobar

次のファイルのリストを検討してください。

hello.txt
some silly name with spaces.txt

を使用すると、2つで"$(output filenames)"はなく1つの文字列が提供されます。
を使用すると、$(output filenames)2つではなく6つの文字列が提供されます。

IFS後者が改行文字に分割され、2つのファイル名を提供するように改行文字のみを設定することでこの問題を解決できます。ただし、これは面倒でグローバルな影響を与え、set -fファイル名が変更されないようにするには、まだワイルドカードを無効にする必要がありますfunny * name.txt

(これまでは、変数拡張を分割しなくても引用符なしのコマンド置換結果を分割する点で、デフォルトではzshと同じですが、デフォルトでは結果をワイルドカードとして表示しません。)

違いを見ることができない理由は、echo取得したすべての引数を単一のスペースで連結して印刷するためです。したがって、まったく同じ出力を生成しますecho foo barecho "foo bar"代わりに、次のようなものを使用すると、printf "<%s>\n" ...パラメータの境界をより明確に表示できます。

$ printf "<%s>\n" foo bar
<foo>
<bar>
$ printf "<%s>\n" "foo bar"
<foo bar>

また見なさい:

おすすめ記事