第32回シェル芸勉強会 Q1・Q2・Q3 の別解

昨日は家に帰るのが遅かったので休みました。

前置き

毎日更新で解くと、普段のシェル芸勉強会で問題を解いているときと違い、問題に取り組んでいる期間が長く、頭に問題が残っていて解答を思いつくので、それを残しています。

Q1の解答3

$ echo 14679 | sed 's#.*#seq 9 | tr -dc &\\\\n#' | sh
1


4

6
7

9

解説

この解答は最終的にshに投げてます。投げる前の出力(shで実行されるコマンド)は次のようになっています。

$ echo 14679 | sed 's#.*#seq 9 | tr -dc &\\\\n#'
seq 9 | tr -dc 14679\\n

seqの連番出力から、必要な数字だけ残しています。

発送のタネは、 第32回シェル芸勉強会 Q1 の解答 - nogiro_iotaのメモ の解答1で出力した

 1
-2
-3
 4
-5
 6
 7
-8
 9

です。
上記の出力はseqから不要な数字を除くため、diffを使って作っていますが、そもそもtrを使えば、不要な数字だけを消せます。

Q2の解答5

$ echo 14679 | diff -u <(seq 9) <(grep -o .) | sed 1,3d | cat <(echo {a..z}|tr \  \\n) - | awk '/[a-z]/{a[NR]=$0}/^ /{print $0}/^-/{print a[++i]}' | tr -d \
1
a
b
4
c
6
7
d
9

解説

問題を誤読していました。
第32回シェル芸勉強会 Q2 の解答 - nogiro_iotaのメモ では、「Q1の結果から始めてQ2の解答を作れ」だと思って解いていましたが、「Q1と同じ入力から始めてQ2の解答を作れ」でした。

Q1の解答1で不要行を消しているところで、そのままアルファベットを出力しました。
前回の投稿のときには、「連続したアルファベットを出すのが難しい」と言っていましたがbashのブレース展開を使うと簡単に作れました。

Q2の解答6

$ echo 14679 | grep -o . | sed 's#.*#sed &i&#' | paste -d\| -s | sed 's#.*#echo {a..z} | tr \\  \\\\n | &#' | bash | awk '{print}/^9$/{exit}'
1
a
b
4
c
6
7
d
9

解説

アルファベットの連番は簡単に作れますが、それをコマンド中に混ぜ込むのは地味にめんどくさいので、アルファベットの連番に元の出力を混ぜ込むようにしました。
文での説明だとたぶん良くわからないので、bashに投げる前の出力をご覧ください。

echo {a..z} | tr \  \\n | sed 1i1|sed 4i4|sed 6i6|sed 7i7|sed 9i9

Q3の解答2

seq 65536 | factor | awk 'NF==2{print "\\<"$2"/tcp\\>"}' | grep -f - /etc/services

解説

こちらも問題の誤読ですね。。。
詳しくは 第32回シェル芸勉強会 Q3 の解答 - nogiro_iotaのメモ に書いていますがざっくり説明すると、「/etc/servisesから素数のポート番号を抜き出す問題だと思ってシェル芸したが、問題をよく読むとサービス一覧が必要で番号ではなかったため慌てて後ろにつけてごまかした」ため、ワンライナーが右往左往してます。(右往左往しても結果が簡単に出てくるのがワンライナーのいいところといえばそうですが。。。)

上記の解答だと、先にポート番号の上限まで素数を作ることで短くしています。