odz buffer

2007-01-29

[]shell のちょっとしたテクニック

後輩が

cat README | tr ' ' '\n' | sort | uniq -c | sort -nr | head

てなテクニックを見て、びっくりしたみたいな話をしていたのだが、こういうパイプラインを利用するテクニックを学んでいないのは色々損な気がする。

ていうか、サーバで丸一日以上かかるような処理を実行するのもしょっちゅうなのに、GNU screen も nohup も知らないってのはいろいろ支障があるような気もするのだが、だれも教えないものかなぁ。

ということで、bash or zsh のちょっとしたテクニックとか*1リダイレクトとかパイプラインは略。

連続実行

単純に連続実行。

% foo; bar

foo が正常終了したときだけ bar を実行

% foo && bar

foo が正常終了しなかったときだけ bar を実行

% foo || bar

&&||は本来は論理演算子だが、C と同じく真偽が決定した時点でそれ以上評価(実行)しない。

configure と make を && で結合するのは定番。

% ./configure && make

job control

コマンドの末尾に & をつけるとバックグランドで実行されるというのは結構知られているのだが、C-z で一時停止して、さらに bg を実行するとフォアグラウンドジョブ をバックグラウンドに出来るのは案外知らない人が多い気がする。

% find / > /dev/null 2>&1
(C-z)

zsh: suspended  find / > /dev/null 2>&1
% jobs
[1]  + suspended  find / > /dev/null 2>&1
% bg
[1]  - continued  find / > /dev/null 2>&1
% jobs
[1]  + running    find / > /dev/null 2>&1
% fg
[1]  + running    find / > /dev/null 2>&1

jobs で実行中の job 一覧、bg で停止した job をバックグラウンド実行。fg で停止中もしくはバックグランド実行中の処理を再度フォアグラウンドで実行できる。

[1] と出ているのは job 番号で、ジョブが複数ある場合に fg %1 とか bg %2 といった具合に job を指定するのに使用する。

今実行中のコマンドに続けて別のコマンドを実行したくなったりした場合、

% foo
(C-z)
% fg && bar

なんてことも出来る。

コマンド置換

`command` か $(command) でコマンドの実行結果がコマンドライン中に展開される。

たとえばカレントディレクトリ以下(サブディレクトリ含む)の "*.c" から strcmp を探したければ

grep -H strcmp $(find . -type f -name "*.c")

などとする*2

プロセス置換

<(command) は command の標準出力をあらわす名前付きパイプのファイル名に置換される。要するに

% foo > foo.out
% bar > bar.out
% diff -u foo.out bar.out

とする代わりに

% diff -u <(foo) <(bar)

と出来る。ただし、あくまでパイプなので seek できないことに注意。zsh なら =(command) という記法もあり、こちらは seek もできる。

履歴

カーソルキーを使った履歴参照は大抵皆知っているのだが、「!」を使った履歴参照は案外知らない人が多い。

!!
一つ前のコマンドを実行
!-n
n行前のコマンドを実行
!string
stringから始まるコマンドのうち、もっとも最近実行したコマンドを実行する

あと、Ctrl + r で後方に向かって履歴をインクリメンタル検索が出来たりして、これも結構便利。

尚、履歴は出来るだけ保存するべし。zsh なら .zshrc にこんなのを書いておく。

HISTFILE=$HOME/.zsh-history
HISTSIZE=100000
SAVEHIST=100000

GNU screen とか nohup とか

SSH などでログインしたマシンで時間のかかる処理を行う場合は GNU screen で pty を切り離せるようにするか、SSH の session が切れても大丈夫なように nohup を使う。さもないと、何かの拍子に SSH の session が切れた場合にプロセスに SIGHUP が送られ途中でプロセスが止まってしまう。

*1csh とか tcsh は知らない

*2:より汎用的には find . -type f -name "*.c" -print0 | xargs -0 -e grep strcmp -H

へげもんへげもん 2007/01/30 22:34 某、日本では(多分)有名なSI企業(多分)へコンサルに行ったときのこと。
あちらの中堅SEさんへ、設定ファイルの編集の仕方を教えた。
そこで、^Aで全件選択、^Cでコピー、^Vでペーストとやったら、
「そんなやり方があったんですが!」と感心されてしまい、
しばらく石になりました。

odzodz 2007/01/31 13:34 それは・・・効率化しようとする意識がないんでしょうね。

elfelf 2007/01/31 13:54 自分が知らないテクニックは世の中にごまんとあると常に思っているかどうかってのもあるでしょうね

H.I.H.I. 2007/02/01 09:11 >grep -H strcmp $(find . -type f -name ”*.c”)
これはコマンド置換の例でしょうけど、少なくともzshなら同じことが
grep -H strcmp **/*.c(.)
でできます。

odzodz 2007/02/01 13:05 > elf さん
うーむ。そういう考え方もありますか。向上心以前に上があることを知らないと。

> H.I. さん
あー、そういうのが出来るのは一応知っているんですが、bash でできないので省略しました。(そっちを使っているとコマンド置換を忘れそうですし)
あと setopt extended_glob するとさらに拡張された glob が使えるようになるってのもありますね。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証