85

一部のbashスクリプトの実行を高速化するために、コマンド置換を使用してコマンドの結果を変数に保持したいのですが、コマンド置換0x0Aにより改行文字がスペースに置き換えられます。例えば:

a=`df -H`

また

a=$( df -H )

さらに処理したい場合は$a、改行文字がスペースに置き換えられ、すべての行が 1 行になり、grep がはるかに難しくなります。

echo $a

コマンド置換によって改行文字が削除されないようにするための簡単なトリックは何ですか?

4

3 に答える 3

136

末尾の改行以外は削除されません

探している改行はそこにありますがecho、変数を引用せずに使用しているため、表示されません。

検証:

$ a=$( df -H )
$ echo $a
Filesystem Size Used Avail Use% Mounted on /dev/sda3 276G 50G 213G 19% / udev 2.1G 4.1k 2.1G 1% /dev tmpfs 832M 820k 832M 1% /run none 5.3M 0 5.3M 0% /run/lock none 2.1G 320k 2.1G 1% /run/shm
$ echo "$a"
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda3       276G   50G  213G  19% /
udev            2.1G  4.1k  2.1G   1% /dev
tmpfs           832M  820k  832M   1% /run
none            5.3M     0  5.3M   0% /run/lock
none            2.1G  320k  2.1G   1% /run/shm
$ 

末尾の改行は削除されます

@ user4815162342 が正しく指摘したように、出力内の改行は削除されませんが、末尾の改行はコマンド置換で削除されます。以下の実験を参照してください。

$ a=$'test\n\n'
$ echo "$a"
test


$ b=$(echo "$a")
$ echo "$b"
test
$

ほとんどの場合echo、削除された改行が追加されるため (-nオプションで呼び出されない限り)、これは問題ではありませんが、プログラムの出力に末尾の改行が複数ある場合がいくつかあり、それらはプログラムにとって重要です。何らかの理由。

回避策

1.ダミーキャラ追加

このような場合、@Scrutinizerが述べたように、次の回避策を使用できます。

$ a=$(printf 'test\n\n'; printf x); a=${a%x}
$ echo "$a"
test


$ 

説明:改行の後に ( を使用して)文字xが出力に追加されprintf x改行はもはや末尾にないため、コマンド置換によって削除されません。次のステップは、演算子 inxを使用して、追加した を削除するです。これで、すべての改行が存在する元の出力が得られました!!!%${a%x}

2. プロセス置換を使用して読み取る

コマンド置換を使用してプログラムの出力を変数に割り当てる代わりに、プロセス置換 を使用してプログラムの出力をread組み込みコマンドにフィードできます ( @ormaajの功績による)。プロセス置換では、すべての改行が保持されます。出力を変数に読み取るのは少しトリッキーですが、次のように実行できます。

$ IFS= read -rd '' var < <( printf 'test\n\n' ) 
$ echo "$var"
test


$ 

説明:

  • 読み取りコマンドの内部フィールド区切り文字を null に設定しIFS=ます。そうreadしないと、出力全体が に割り当てられvarず、最初のトークンのみが割り当てられます。
  • readoptions で呼び出します-rd ''。はr、バックスラッシュが特殊文字として機能するのを防ぎ、d ''区切り文字を何も設定しないようにするためのものです。これにより、 read は最初の行だけでなく、出力全体を読み取ります。

3. パイプから読み取る

コマンドまたはプロセス置換を使用してプログラムの出力を変数に代入する代わりに、プログラムの出力をreadコマンドにパイプすることができます ( @ormaajの功績)。パイピングはすべての改行も保持します。ただし、今回はビルトインを使用して、シェルのオプションの動作を設定したことに注意lastpipeください。これは、現在のシェル環境でコマンドを実行するために必要です。それ以外の場合、変数はサブシェルで割り当てられ、残りのスクリプトからアクセスできなくなります。shoptread

$ cat test.sh 
#!/bin/bash
shopt -s lastpipe
printf "test\n\n" | IFS= read -rd '' var
echo "$var"
$ ./test.sh 
test


$
于 2013-03-03T09:46:04.873 に答える