【問題と解答】第29回激しいシェル芸勉強会

Sat Jul 1 15:31:59 JST 2017 (modified: Sat Dec 14 19:05:56 JST 2019)
views: 4834, 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" # 
    
    

もっと良い解答。

ノート   このエントリーをはてなブックマークに追加 
 

prev:【問題のみ】第29回激しいシェル芸勉強会 next:第29回シェル芸勉強会まとめ

やり散らかし一覧

記事いろいろ