1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

bashのコマンド置換で複数行を処理したい

Last updated at Posted at 2018-03-22

bashのコマンド置換で複数行を処理したい

3行まとめ

  • bash(POSIXシェル)のコマンド置換を使うと、コマンド出力をコマンドとして実行させられて便利
  • 入れ子にできるため、$()がおすすめ
  • 出力が複数行の場合は、while readなどで1行ずつ取り出して$()に流す

コマンド置換の例

※確認環境はRed Hat Enterprise Linux Workstation release 6.8 (Santiago)です。

 bashのコマンド置換を使うと、コマンド出力をコマンドとして実行させることができます。
 以下例を見てみましょう。通常、echoの後に文字列を続けて入力するとその文字列がそのまま返ってきます。

$ touch hoge
$ ls -la hoge
-rw-rw-r--. 1 testuser testuser 0  3月 22 11:07 2018 hoge
$ echo chmod 666 hoge
chmod 666 hoge

 次のように、この文字列を$()でくくってあげると、くくられた文字列をコマンドとして解釈・実行させることができます。これがコマンド置換になります。

$ touch hoge
$ ls -la hoge
-rw-rw-r--. 1 testuser testuser 0  3月 22 11:07 2018 hoge
$ echo $(chmod 666 hoge)

$ ls -la hoge
-rw-rw-rw-. 1 testuser testuser 0  3月 22 11:07 2018 hoge

 実現方法としては、以下2通りあるのですが、$()で実現する方をお勧めします。

  • `コマンド`
  • $(コマンド)

$()を使うメリットとしては以下があります。

  • 入れ子にできる

コマンド出力が複数行に渡る場合

 シェルの出力結果をコマンド置換したい場合は、$(./test.sh)などとします。出力が1行しかない場合は何も考えなくてもよいのですが、複数行に渡る場合工夫が必要です。

 次のようなシェルをコマンド置換するケースを考えてみましょう。

test.sh
#!/bin/sh

TARGET="hoge"

echo "chmod 700 ${TARGET}"
echo "date"

 そのまま実行すると以下のように表示されます。

$ ./test.sh 
chmod 700 hoge
date

 コマンド置換してみると、dateまで含めてchmodの引数として処理されてしまっています。うまくないです。

$ $(./test.sh)
chmod: cannot access `date': そのようなファイルやディレクトリはありません

 for でコマンドの結果を取り出して$()に渡してみると、こうなりました。

$ for v in $(./test.sh); do echo $($v); done
chmod: missing operand
詳しくは `chmod --help' を実行して下さい.

コマンドが見つかりません。 

コマンドが見つかりません。 

2018年 3月 22日 木曜日 14:26:36 JST

 コマンド置換せずに出力させてみると、空白で分割されてしまっているようです。(IFSを設定してあげればうまくいくかもしれない)

$ for v in $(./test.sh); do echo $v; done
chmod
700
hoge
date

 while readで1行ずつ取り出して$()に渡してあげると、うまくいきました。

$ ./test.sh | while read f; do $(echo $f); done
2018年  3月 22日 木曜日 14:29:02 JST
$ ls -la hoge
-rwx------. 1 testuser testuser 0  3月 22 11:07 2018 hoge

while readで取り出される値を1つずつ見てみると、1行ずつ取り出されていますね。

$ ./test.sh | while read f; do echo $f; done
chmod 700 hoge
date

コマンド置換の際、改行文字の取り扱いには注意ですね。ヘルプより抜粋ですが、以下のような動きになります。

  • 末尾の改行文字が削除される
  • 文字列の途中にある改行文字は削除されませんが、単語分割の際に削除されることがある

 改行を残したければ、"$(コマンド)"というような記載になります。1

参考

  1. シェルスクリプトで実行したコマンドの結果の改行をそのままにする

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?