【何を】「第57回シェル芸勉強会」の解答例【今更】


Q1

次のファイルから今の元号の数を数えてください。

$ cat reiwa
令和昭和令和大正令和明治大正享保
令和昭和平成令和令和応和令和令和
令和大正大正昭和令和平成令和令和
令和元禄文久昭和大正天保令和令和
令和安政安永弘化慶応令和令和令和
令和平成平成明治宝暦元和正保慶安

A1

# ファイルにある元号は全て2文字であることを利用
$ grep -o .. reiwa | sort | uniq -c | awk '/(令|令)/{n+=$1}END{print n}'
20

Q2

次のファイルの中の旧字体の漢字を、新字体に変換してください。

$ cat kanji2
寫眞
星圖
學校
鐵道
鐵砲彈
燈臺
兩腕

A2

# PerlのLingua::JA::Mojiモジュール(https://metacpan.org/dist/Lingua-JA-Moji)を使用
$ perl -M'Lingua::JA::Moji' -M'utf8' -C -nlE 'say Lingua::JA::Moji::old2new_kanji($_)' kanji2
写真
星図
学校
鉄道
鉄砲弾
灯台
両腕

Q3

次のファイルから、日本語にない漢字を抽出してください。

$ cat kanji
无产阶级文化大革命,通称文化大革命、简称文革,是中华人民共和国历史上的一场政治運動

文化大革命 | Wikipedia(https://zh.wikipedia.org/wiki/文化大革命)
https://zh.wikipedia.org/wiki/Wikipedia:CC_BY-SA_3.0协议文本

A3

# uninameで漢字の種類を調べる
$ cat kanji | uniname -e 2>/dev/null | grep 'Unknown character in range CJK' | awk '{print $4}'
无
产
阶
级
简
华
历
场
协
议

Q4

次のファイル内の漢字を簡体字に変換してください。

$ cat hongkong
西營盤站
香港大學站
荃灣站
黃大仙站
鑽石山站
觀塘站

A4

# Webスクレイピングで手抜き :-)
$ curl -sd "text1=$(cat hongkong)&kbn1=2" https://dokochina.com/sim2traconv.php | sed "1,/name='text2'/d" | sed '/<\/form>/,$d' | sed 's/<.*//'
西营盘站
香港大学站
荃湾站
黄大仙站
钻石山站
观塘站

Q5

次のシェルスクリプトについて./hoge.bash &を実行の後、1番目のdateの実行から2番目のdateの実行を40秒以上あとに遅らせてください。

$ cat hoge.bash
#!/bin/bash

date
sleep 30
date

A5

# 普通に実行した例:
$ ./hoge.bash &
[1] 12942
2022年  3月  2日 水曜日 16:16:00 JST
2022年  3月  2日 水曜日 16:16:30 JST
# killでプロセスにシグナルを送ってやればよい
$ ./hoge.bash &
[1] 15618
2022年  3月  2日 水曜日 16:26:00 JST
$ kill -STOP $!; sleep 40; kill -CONT $!

[1]+  停止                  ./hoge.bash
2022年  3月  2日 水曜日 16:26:45 JST
[1]+  終了                  ./hoge.bash

Q6

小問1

次のような手続きを実行すると、ある時点でgrepが終わらなくなります。

$ echo うんこ > unko
$ grep うんこ unko | cat >> unko
$ grep うんこ unko | cat >> unko
$ grep うんこ unko | cat >> unko
・・・
$ grep うんこ unko | cat >> unko
(止まらなくなる)

このgrepを直接Ctrl+Ckillせず、unkoファイルに細工をする方法で止めてください。

小問2

できた人は、次のwhile文を止めてみてください。

$ echo うんこ > unko
$ while grep うんこ unko | cat >> unko ; do : ; done

A6

小問1

# ファイルサイズを0にすればよい
$ truncate --size=0 unko

小問2

# ※環境によっては上手くいかないかもしれない
# 1. unkoファイルをunkoディレクトリに強引にすり替えた後、pkill grepするとwhileループが止まる
# 2. 1秒ほど待ってから後片付け
$ while [ -f unko ] ; do rm -f unko && mkdir unko ; done ; pkill grep ; sleep 1 ; rmdir unko

Q7

x^8 - y^8を因数分解してください。できた人はsin xをテイラー展開でもしててください。

A7

# 2つともPARI/GPのgpに丸投げ :-)
$ echo 'factor(x^8 - y^8)' | gp -fq | sed -E 's/\[/(/;s/ 1\]/)/;s/  +//g;/^$/d' | sed -Ez 's/\n/*/g;s/\*$/\n/'
(x - y)*(x + y)*(x^2 + y^2)*(x^4 + y^4)
$ echo 'sin(x)' | gp -fq
x - 1/6*x^3 + 1/120*x^5 - 1/5040*x^7 + 1/362880*x^9 - 1/39916800*x^11 + 1/6227020800*x^13 - 1/1307674368000*x^15 + O(x^17)

Q8

7/17を小数になおすと循環小数(ある桁以降が同じ数字の並びの繰り返しになる小数)になります。繰り返される数字の並びについて、最短のものを求めてください(循環の始まる先頭は捉えなくてかまいません)。

A8

# grepで繰り返し2回分を抽出後、sedで1回分に切り取り
$ echo 'scale=1000;7/17' | bc -l | sed -z 's/[\n\\]//g;s/$/\n/' | grep -Po '(\d+?)\1' | sed -E 's/([0-9]+)\1/\1/' | head -n1
4117647058823529
Written on March 16, 2022