パイプで連結された長ったらしいコマンド群を理解するには、個々に分割して出力結果を確認する
yahoo知恵袋で次の質問投稿がありました。
$ cat manpage.txt | awk 'BEGIN{RS="";FS="\n"}{print $1 $2 $3}' | grep -e ' -' | sed -e 's/^ +//g' -e 's/ +/ /g' -e 's/, /,/' -e 's/ /:/' -e 's/ +//g' -e 's/。.*//g' | grep -v '^--' | awk 'BE GIN{FS=":"}{printf "%-29s | %s%s\n",$1,$2,$3}' | sort -f
どのコマンドがどの操作をしているのか動作する順番に教えて欲しいです。
出力結果は以下のリンク先の通りです。
https://scrapbox.io/today-script/sed%2Fawk:_%E3%81%93%E3%82%93%E3%81%AA%E3%81%93%E3%81%A8%E3%81%A7%E3%81%8D%E3%81%9F%E8%87%AA%E6%85%A2
一見、長ったらしくて手に負えられないと思うかもしれないが、1個ずつコマンドを分解すれば、そんなに難しいことはしていない。 以下のように回答しておきました。
コマンドを分解して、各コマンドの出力結果をファイルに出力し、そのファイル内容を確認されてみては如何でしょうか。
例えば、以下のようにコマンドを分解したときに、a.txtとb.txtを比較すれば、b.txtを出力したawkコマンドがどんな処理をしているかイメージがつくと思います。1cat manpage.txt > a.txt 2awk 'BEGIN{RS="";FS="\n"}{print $1 $2 $3}' a.txt > b.txt 3grep -e ' -' b.txt > c.txt 4sed -e 's/^ \+//g' c.txt > d.txt 5sed -e 's/ \+/ /g' d.txt > e.txt 6sed -e 's/, /,/' e.txt > f.txt 7sed -e 's/ /:/' f.txt > g.txt 8sed -e 's/ \+//g' g.txt > h.txt 9sed -e 's/。.*//g' h.txt > i.txt 10grep -v '^\--' i.txt > j.txt 11awk 'BEGIN{FS=":"}{printf "%-29s | %s%s\n",$1,$2,$3}' j.txt > k.txt 12sort -f k.txt > l.txt
上から順に軽く説明すると、以下のような感じになる。
1行目 | manpage.txtの内容を出力 |
2行目 | \nを区切り文字として分割した時の1〜3列を出力 |
3行目 | ' -'を含む行を出力 |
4行目 | 先頭の連続した空白を削除して出力 |
5行目 | 連続した空白を1個の空白に置換して出力 |
6行目 | 最初のカンマの直後の空白を削除して出力 |
7行目 | 最初の空白をコロンに置換して出力 |
8行目 | 連続した空白を削除して出力 |
9行目 | 。以降を削除して出力 |
10行目 | 先頭が--から始まらない行を出力 |
11行目 | コロンを区切り文字として分割した時の1〜3列を書式に従って出力(1列目は29桁左寄せ指定) |
12行目 | 行を並び替えて出力 |
※awkの組み込み変数
FS:フィールドの区切り文字(デフォルトはスペース)
RS:レコードの区切り(デフォルトは改行)
※printfの書式は以下リンク先を参照
https://www.seiai.ed.jp/sys/text/csb/chs05/c05b050.html
保守業務でバッチシェルを見ること多々あるが、今回のようにパイプなどで繋がれた長ったらしいコマンドに出くわすこともある。 意図を理解するには、やはり分割して動作を確認することが基本となる。