【問題と解答】第29回激しいシェル芸勉強会
Sat Jul 1 15:31:59 JST 2017 (modified: Sat Dec 14 19:05:56 JST 2019)
views: 5181, keywords:コマンド,UNIX/Linuxサーバ,勉強会,シェル芸,シェル芸勉強会 この記事は最終更新日が4年以上前のものです。
問題で使うファイル等
GitHubにあります。ファイルは
https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.29
にあります。
クローンは以下のようにお願いします。
git clone https://github.com/ryuichiueda/ShellGeiData.git $
環境
解答例はUbuntu Linux 16.04 で作成。Macの場合はcoreutilsをインストールの上、gsedをつかいましょう。BSD系の人は玄人なので各自対応のこと。
イントロ
Q1
次の2つのファイルは、講義で出した課題1,2それぞれの点数です。
cat kadai1
$ 001 山田 20
002 出川 30
005 鳥海 44
cat kadai2
$ 001 山田 20
003 上田 15
004 今泉 22
005 鳥海 44
両方に名前のある人については点数を合計して、次のように全員の得点リストを作ってください。
001 山田 40
002 出川 30
003 上田 15
004 今泉 22
005 鳥海 88
解答
join -a 1 -a 2 -1 1 -2 1 kadai{1,2} | awk '{print $1,$2,$3+$5}'
$ 001 山田 40
002 出川 30
003 上田 15
004 今泉 22
005 鳥海 88
Q2
次の2つのファイルは、5回の講義の出欠と6回目の講義で出席した人の番号のデータです。attendに6回目の講義の出欠を反映したデータを標準出力に出力してください。
cat attend
$ 001 山田 出出欠出出
002 出川 出出欠欠欠
003 上田 出出出出出
004 今泉 出出出出出
005 鳥海 欠出欠出欠
cat attend6
$ 001,005,003
解答
tr , '\\n' < attend6 | sort | sed 's/$/ 出/' |
$ join -a 1 attend - |
awk 'NF==3{print $0"欠"}NF==4{print $1,$2,$3$4}'
Q3
次の2つのファイルは5回の講義の出欠とテストの成績を記録したファイルです。
###$1: 番号, $2: 名前, $3: 出欠 ###
cat attend
$ 001 山田 出出欠出出
002 出川 出出欠欠欠
003 上田 出出出出出
004 今泉 出出出出出
005 鳥海 欠出欠出欠
###$1: 番号, $2: テストの点数(受けてない人のデータは無い)###
cat test
$ 001 90
002 78
004 80
005 93
こういうルールで、最終的な点数を出して、番号、名前、点数を記録したファイル作ってください。
- 出席が過半数に満たない人、テストを受けていない人は0点
- 出席が過半数の人はテストの点数を採用
解答
join -a 1 -o 1.1 1.2 1.3 2.2 -e 0 attend test |
$ awk '/(.*欠){3}/{$4=0}{print}'
001 山田 出出欠出出 90
002 出川 出出欠欠欠 0
003 上田 出出出出出 0
004 今泉 出出出出出 80
005 鳥海 欠出欠出欠 0
Q4
Q4.1
次の出力をパイプで受けて
echo -1 4 5 2 42 421 44 311 -9 -11 $
次のように同じ桁のものを横並びに出力を得てください。横に並べる時の順番は任意とします。また、この出力のように正の数と負の数を分けます。
-11
-9 -1
2 4 5
42 44
311 421
Q4.2
次の出力をパイプで受けて
echo -1 +4 5 2 42 421 44 311 -9 -11 $
次のように同じ桁のものを横並びに出力を得てください。Q1.1と同じく横に並べる時の順番は任意とします。
-11
-9 -1
2 +4 5
42 44
311 421
解答
Q4.1
echo -1 4 5 2 42 421 44 311 -9 -11 | xargs -n 1 | sort -n |
$ awk 'length(a) != length($1){print ""}{printf("%d ",$1);a=$1}' |
awk 'NF'
-11
-9 -1
2 4 5
42 44
311 421
Q4.2
awk内で1をかけると+符号が外れるので、符号を外して桁数を比較すると先ほどの解答例が転用できます。
echo -1 +4 5 2 42 421 44 311 -9 -11 | xargs -n 1 | sort -n |
$ awk 'length(a*1) != length($1*1){print ""}{printf("%s ",$1);a=$1}' |
awk 'NF'
-11
-9 -1
+4 2 5
42 44
311 421
Q5
次のファイルの中身について、
cat triangle
$ 1
3 9
7 a 6
8 4 2 5
次のように右に転がしてください。できる人はawkを使わないでやってみましょう。
8
4 7
2 a 3
5 6 9 1
解答
四角にして回すと楽です。
cat triangle | sed 's/ /0 /g' | sed 's/\\([^ ]\\)0/\\1/g' |
$ tac | rs -T | tr -d 0 | sed 's/ / /g' | sed '1s/^/ /' |
sed '2s/^/ /' | sed '3s/^/ /'
8
4 7
2 a 3
5 6 9 1
Q6
次の1から100までの素数を書いたファイル(いくつか欠番が存在)について、
cat prime
$ 2 3 5 7 11 13 17 19 31 37 41 43 47 53 59 67 71 73 79 83 89 97
次のように欠番のところで折り返してください。(ワンライナーの中に欠番を直接書かないでくださいね。)
2 3 5 7 11 13 17 19
31 37 41 43 47 53 59
67 71 73 79 83 89 97
解答
cat prime | xargs -n 1 | cat - <(seq 1 100 | factor |
$ awk 'NF==2{print $2}') | sort -n | xargs |
awk '{for(i=1;i<NF;i+=2){if($i==$(i+1)){printf("%d ",$i)}else{print "";i-=1}}}' |
awk 'NF'
2 3 5 7 11 13 17 19
31 37 41 43 47 53 59
67 71 73 79 83 89 97
Q7
リポジトリ内のnyaan.htmlは、ブラウザで見ると次のように見えます。
次のようにcatから始めて、この文字を(大きなまま)端末上に表示してみてください。
cat ./nyaan.html | ... $
できる人は小さい通常の文字で「にゃーん」と出してみてください(これは解答例を考えていません)。
解答
cat ./nyaan.html | nkf --numchar-input |
$ sed 's/<[^<]*>//g' | sed 's/"/"/g'
Q8
次のshellgeiファイルについて、
cat shellgei
$ m
""m m "m # # # #
mm # # #mmm""" m"
" m" mmm"" # # # m" # mm""m
m" #mm m" # m" " # #
"mm"" """" " m" #" m" #
次のように、文字の無い列を詰めてください。
m
""m m "m # # # #
mm # # #mmm""" m"
" m" mmm"" # # # m" # mm""m
m" #mm m" # m" " # #
"mm"" """" "m" #" m" #
解答
cat shellgei | sed 's/ /@/g' | sed 's/./& /g' |
$ awk '{for(i=1;i<=NF;i++){if($i!="@")a[i]=$i}}END{for(i=1;i<=NF;i++){b=a[i]==""?"x":" ";printf b}}END{print ""}' |
cat - shellgei |
awk 'NR==1{a=$0}{for(i=1;i<=length($0);i++){if(substr(a,i,1)!="x")printf substr($0,i,1)};print ""}'
m
""m m "m # # # #
mm # # #mmm""" m"
" m" mmm"" # # # m" # mm""m
m" #mm m" # m" " # #
"mm"" """" "m" #" m" #
もっと良い解答。
#シェル芸 #福岡 Q8解答
— ぱぴろんちゃん👓 (@papiron) 2017年7月1日
$ cat shellgei | tr ' ' '-' | sed 's/./& /g;s/ $//' | rs -T | grep -v '^[- ]*$' | rs -T | tr -d ' ' | tr - ' '