[解決済み] 改行文字を削除するbashコマンドの代入を避けるには?
質問
bashスクリプトの実行を高速化するために、コマンドの結果をコマンド置換を使って変数に保持したいのですが、コマンド置換は
0x0A
の改行文字をスペースに置き換えます。たとえば
a=`df -H`
または
a=$( df -H )
さらに処理を行いたい場合
$a
を処理したい場合、改行文字はスペースに置き換えられ、すべての行が1行になり、grepするのが非常に難しくなります。
echo $a
コマンド置換で改行文字が削除されないようにするための簡単なトリックは何でしょうか?
どのように解決するのですか?
末尾にない改行が削除されない
探している改行はそこにあります。
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
$
末尾 は削除されます。
として ユーザー4815162342 が正しく指摘したように、出力内の改行は削除されませんが。 末尾の改行 はコマンド置換で除去されます。以下の実験を参照してください。
$ a=$'test\n\n'
$ echo "$a"
test
$ b=$(echo "$a")
$ echo "$b"
test
$
ほとんどの場合、これは重要ではありません。
echo
は削除された改行を追加するからです (ただし、このコマンドが
-n
オプションで呼び出されない限り)、しかし、プログラムの出力に複数の末尾の改行があり、それが何らかの理由で重要であるようなエッジケースがいくつかあります。
回避策
1. ダミー文字を追加する
この場合 スクリプター が述べているように、以下のような回避策をとることができます。
$ a=$(printf 'test\n\n'; printf x); a=${a%x}
$ echo "$a"
test
$
説明
文字
x
が出力に追加されます(
printf x
を使って)、改行の後に追加されます。改行が
末尾の
でないため、コマンドの置換では削除されません。次のステップでは
x
を使って、追加した
%
演算子で
${a%x}
. これで、すべての改行が含まれた元の出力が得られました!
2. プロセス置換を使った読み込み
プログラムの出力を変数に代入するためにコマンド代入を使うのではなく、代わりに
プロセス代入
に送り、プログラムの出力を
read
組み込みコマンド(クレジット
ormaaj
). プロセス置換ではすべての改行が保存されます。出力を変数に読み込むのはちょっと面倒ですが、次のようにすればよいでしょう。
$ IFS= read -rd '' var < <( printf 'test\n\n' )
$ echo "$var"
test
$
説明
-
を設定します。
内部フィールドの区切り文字
で、readコマンドをnullにすると
IFS=
. それ以外の場合はread
に出力全体を割り当てることはできません。var
には割り当てられず、最初のトークンのみが割り当てられます。 -
を呼び出します。
read
をオプションで起動します。-rd ''
. はr
はバックスラッシュが特殊文字として機能しないようにするためのもので、バックスラッシュがある場合はd ''
で区切り文字を無にすると、read が最初の行だけでなく、出力全体を読み込むようになります。
3. パイプからの読み込み
コマンドやプロセス代入を使ってプログラムの出力を変数に代入する代わりに、プログラムの出力をパイプで
read
コマンドを使うことができます (クレジット
ormaaj
). パイピングはすべての改行も保存します。ただし、今回は
lastpipe
シェルのオプション動作として
は
shopt
ビルトイン
. これは
read
コマンドが現在のシェル環境で実行されるようにするためです。そうでなければ、変数はサブシェルで割り当てられ、スクリプトの残りの部分からアクセスできなくなります。
$ cat test.sh
#!/bin/bash
shopt -s lastpipe
printf "test\n\n" | IFS= read -rd '' var
echo "$var"
$ ./test.sh
test
$
関連
-
[解決済み] Bashスクリプトのソースディレクトリをスクリプト自体から取得するにはどうすればよいですか?
-
[解決済み] Bashシェルスクリプトでディレクトリが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashで通常のファイルが存在しないかどうかを判断する方法を教えてください。
-
[解決済み] Bashで文字列変数を連結する方法
-
[解決済み] Bash prints リテラルの改行をエコーする \n
-
[解決済み] Bashスクリプトからプログラムが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashでコマンドライン引数を解析するには?
-
[解決済み] Vimで文字を改行で置き換える方法
-
[解決済み] Bashでコマンドの出力に変数を設定するにはどうすればよいですか?
-
[解決済み] Bashはどのように異なるディレクトリコンテキストでコマンドを実行できますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン