bash変数の改行


9

私はbash変数に複数の行を格納しようとしていますが、動作しないようです。

たとえば、/bin1行に1つのファイルをリストしてに保存すると$LS$LSstdinとしてに渡されwc、常に1が返されます。

$ ls -1 /bin | wc -l
134
$ LS=$(ls -1 /bin); wc -l <<< $LS
1

画面に出力しようとすると、さまざまな結果が得られます。echoすべての行を1行にprintf出力し、最初の行のみを出力します。

#!/bin/bash
LS=$(ls -1 /bin)
echo $LS
printf $LS

では、bash変数には複数の行を含めることができますか?

回答:


15

あなたは二重引用符にそれを必要とする(そして、あなたはすべき 引用変数を倍増、ほとんどの場合):

echo "$LS"

ただし、変数の内容を出力するためにエコー使用せず代わりにprintfを使用してください。

printf '%s\n' "$LS"

1
全体的な答えをより細かく言えば、printfはフォーマット文字列が最初のパラメーターであることを期待しているため、期待どおりに表示されませんでした。彼らがprintfからの出力で改行を見たい場合は、スペースで任意に分割して、printf "%s\n" $LSそれを行います。
ジェフシャラー

%LSは$ LSである必要があります(このような短い編集はできませんでした)
ジェフシャラー

ありがとう!それはもちろんでも動作しますwcし、他のコマンド:wc -l <<< "$LS"
Wizard79

1
@JeffSchaller:いいえ、この場合、変数の引用符を外さないでprintf '%s\n' "$LS"ください。改行を表示する場合にのみ使用してください。入力ミスです。修正しました!
cuonglm

変数を出力するためにエコーを使用すべきではないのはなぜですか?
123

9

改行は変数内にあります。LS=$(ls -1)変数LSをの出力に設定しますls -1(これによりls、出力が端末に送られる場合を除いて、と同じ出力が生成されます)。

問題は、値を出力するときに改行を削除することです。シェルスクリプトで$LSは、「変数の値」を意味するのではなく、「の値をLS取り、LSそれを単語に分割しIFS、各単語をグロブパターンとして解釈する」ことを意味します。の値を取得するにはLS、を記述"$LS"するか、より一般的に$LSは二重引用符で囲む必要があります。

echo "$LS"値を出力しLS、バックスラッシュ文字を解釈し、で始まるいくつかの値を除いて、いくつかのシェルを除き、-

printf "$LS"LSパーセントまたはバックスラッシュ文字を含まず、(ほとんどの実装では)で始まらない限り、の値を出力します-

の値をLS正確に出力するには、を使用しますprintf %s "$LS"。最後に改行が必要な場合は、を使用しますprintf '%s\n' "$LS"

$(ls)一般的に、ではない、現在のディレクトリ内のファイルのリスト。これは、ファイル名を十分に使いこなしていない場合にのみ機能します。ファイル名(ドットファイルを除く)のリストを取得するには、ワイルドカードを使用する必要があります*。結果は文字列ではなく文字列のリストなので、文字列変数に割り当てることはできません。files=(*)それらをサポートするシェル(ksh93、bash、zsh)で配列変数を使用できます。

詳細については、「シェルスクリプトが空白やその他の特殊文字で詰まるのなぜですか?」を参照してください


printf "$ LS"は、echoと同様に、バックスラッシュ文字の解析にも屈します
cnst

0

前述の

printf '%s\n' "$LS"

唯一の正しい解決策です。

私は他のソリューション提案、両方を持つことを実証しようechoとはprintf、単に正常に動作しません。

$ mkdir t
$ cd t
$ touch \\n
$ LS=$(ls -l)
$ echo "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf "$LS\n"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf '%s\n' "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ ls -l
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ rm \\n
$ cd ..
$ rmdir t
$

V=$(printf 'line0:\\n\\n\nline1.\n') printf '%s\n' "$V"とでテストすることもできます。)

一方\n、ファイル名はそれほど一般的ではないかもしれませんがgit diff、変数に格納すると、リテラルに遭遇する可能性\nが劇的に高まります。


注意kshしてzshも、サポートprint -r -- "$LS"zshもが持っていますecho -E - $LScsh持っているecho $LS:q$ LSは空で、最初の場所で$ LSに複数行の値を取得すると、CSHにはかなりトリッキーである場合には出力改行文字ませんが。
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.