要約
・zshの場合read -d ''
を利用して右方向代入ができる。Bash(version 4.2以降[1])でも以下の準備をすれば同様の操作ができる。
・bashでshopt
コマンドでlastpipe
オプションをオンにする(shopt -s lastpipe
)。
・インタラクティブモード(対話的に入力する場合)ではset
コマンドでモニターオプションをオフにする(set +m
)。
はじめに
shellscriptにおいて、コマンドをパイプでつないで得た結果を、そのまま右方向に変数で代入したいことがある。zshでは上記の方法で実現できた。
( [2]ShellScript: zsh: パイプからの入力を変数へ代入する(右方向への代入)。 )
bash(4.2以降)でも右方向への代入を実現できる。
環境
・当方のMacのbashではこの方法はできませんでした(考察参照)。
・ラズベリーパイ3B+のbashではできました。
bash; GNU bash, バージョン 5.0.3(1)
OS; Raspbian GNU/Linux 10 (buster)
model; Raspberry Pi 3 Model B Plus Rev 1.3
bash; GNU bash, version 3.2.57(1)
zsh; 5.8
OS; 11.2.2
準備
shoptコマンド
shoptコマンドとは、はbashの動作設定(シェルオプション)を表示、設定するコマンド[5]。(shellのoptionという意味?)
-sでオプションをセット(set)、-uでオプションを解除(unset)。
lastpipeオプションをオンにしてかつ、ジョブコントロールがオフになっていると、最後のパイプで繋いだコマンドはバックグラウンドではなくカレントシェルで実行される。(なので、最後のパイプ以降の変数は現在のシェルでとりだせる。)
lastpipe
If set, and job control is not active, the shell runs the last command of a pipeline not executed in the background in the current shell environment.[6]
setコマンド
setコマンドはシェルの設定を確認、変更するコマンド[7][8]。
set +m
でモニターオプションを無効にするとのことです[9]。
zshにおけるreadコマンドを用いた右方向代入
・read -d ''
・zshは最後のパイプ以降のコマンドがカレントシェルで実行されることを利用した方法1。
・-d ''
とすることで代入する文字列に改行が含まれても対応できるようにする。
$ echo 'line1\nline2' | read -d '' anArg
$ echo "$anArg"
line1
line2 #結果
その他の注意点(bash)
・インタラクティブモードで行う場合とスクリプトファイルを実行する場合とがあり[10]、それらの間で異なる点が今回は1点ある。前者はset +m
が必要である。
・bashの場合echo
コマンドでエスケープシーケンスを解釈させる場合は-e
オプションが必要(zshの場合は不要)。
$ echo 'line1\nline2'
line1\nline2 #エスケープシーケンスが解釈されない。
$ echo -e 'line1\nline2'
line1
line2 # 改行されている。
・変数に収めたものを、改行付きで出力する場合、変数をダブルクオートで囲む必要がある[11][13]。
追記2021/04/05
参考13を追加した
OK ; "$anArg"
NG ; $anArg
方法(コード)
インタラクティブモードの場合
$ shopt -s lastpipe; set +m; echo -e 'line1\nline2' | read -d '' anArg; echo "$anArg"
line1
line2 # 結果
シェルスクリプトファイルを実行する場合
・以下の内容のスクリプトファイルを作成し(test.shなど)、chmod
で実行権限を与え、実行する(./test.sh)。
#!/bin/bash
shopt -s lastpipe
echo 'line1\nline2' | read -d '' anArg
echo "$anArg"
line1
line2 #結果
考察
shoptコマンドで設定可能なオプション一覧を得ることができる[12]。当方のMacのシェルをbashに変更後、shoptコマンドで一覧を確認したところlastpipeがなかった。bashのバージョンが古いからかもしれない(が確認はしていない)。
参考
[1]bash: Assign variable from pipe? - Stack Overflow, https://stackoverflow.com/questions/42963395/bash-assign-variable-from-pipe
[2]ShellScript: zsh: パイプからの入力を変数へ代入する(右方向への代入), https://qiita.com/BlackCat_617/items/ffeb455117483eb2baa2
[3]Raspberry Piのバージョンを確認する方法 - Reasonable Code, https://reasonable-code.com/raspberrypi-version-show/
[4]ラズベリーパイ用OS Raspbianのバージョンの調べ方と歴代バージョンについて│FABSHOP.JP -デジタルでものづくり! ファブショップ !, https://www.fabshop.jp/%E3%83%A9%E3%82%BA%E3%83%99%E3%83%AA%E3%83%BC%E3%83%91%E3%82%A4%E7%94%A8os-raspbian%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%AE%E8%AA%BF%E3%81%B9%E6%96%B9%E3%81%A8%E6%AD%B4%E4%BB%A3/
[5]【 shopt 】コマンド――bashのシェルオプションを表示/設定する:Linux基本コマンドTips(361) - @IT, https://www.atmarkit.co.jp/ait/articles/1912/06/news030.html
[6]The Shopt Builtin (Bash Reference Manual), https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
[7]【 set 】コマンド――シェルの設定を確認、変更する:Linux基本コマンドTips(205) - @IT, https://www.atmarkit.co.jp/ait/articles/1805/10/news023.html
[8]The Set Builtin (Bash Reference Manual), https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
[9]【 set 】コマンド(応用編1)――ファイルの上書きやシェルの終了、ジョブ終了後の通知動作を変更する:Linux基本コマンドTips(207) - @IT, https://www.atmarkit.co.jp/ait/articles/1805/17/news034.html
[10]2つの顔を持つソフトウェア:シェル:ステップ・バイ・ステップ・シェルスクリプト(1) - @IT, https://www.atmarkit.co.jp/ait/articles/0007/27/news002.html
[11]シェルスクリプトで変数に改行コードを含める方法 | 俺的備忘録 〜なんかいろいろ〜, https://orebibou.com/ja/home/201411/20141114_001/
[12]shoptコマンドで設定できるbashの便利設定まとめ | 俺的備忘録 〜なんかいろいろ〜, https://orebibou.com/ja/home/201704/20170411_001/
[13]bashで複数行の文字列の代入と、ヒアドキュメントを使わずに変数に格納する方法 - それマグで!, https://takuya-1st.hatenablog.jp/entry/2017/03/22/144700