第21回シェル芸勉強会に大阪サテライト会場から参加しました。
【問題のみ】第21回未経験者大歓迎!誰でも働けるアットホームな職場ですシェル芸勉強会 – 上田ブログ
自分の解答を記載します。
A1
PDF からテキストを抽出するお題。
poppler
パッケージに付いてくるpdftotext
を使う。
https://www.archlinux.org/packages/extra/i686/poppler/files/
$ pdftotext bba.pdf - 2> /dev/null 群馬のシャブばばあ hoge.txt[2016/02/09 22:30:32]
A2
SJIS で1行のデータを UTF-8 で定数文字折り返しデータに変換する。
sed
はマルチバイト対応なので折りたたむことができる。
cat anydata.cp932 | iconv -f SJIS | sed -E 's/.{35}/&\n/g'
A3
2016年の日曜日を全て列挙する。
date
を使うのが正攻法だと思ったから、別の手法を考えた。
cal
はカレンダーを出力するコマンド。
引数を与えると(cal 〈day〉 〈month〉 〈year〉
)表示する月を変更できる。
$ cal 1 4 2016 April 2016 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
解答
$ echo {1..12} | xargs -n 1 | xargs -I% cal 1 % 2016 | grep '^.[^[:space:]]' | awk 'START{i=0}$1=="Su"{i++}$1!="Su"{printf ("2016%02d%02d\n",i,$1)}' | wc # 解答省略用 wc 52 52 468
A4
タグのついたデータを、新しいデータで更新する。
タグをキーとする連想配列を上書きするという発想しか出てこなかった。
連想配列といえばawk
である。
$ cat data newdata | awk '{a[$1]=$2}END{for(v in a){print v,a[v]}}' 002 ******* 003 群馬のシャブばばあ 004 尾崎んちのババア 005 純愛ババア学園 001 あみだばばあ
A5
a.bash
午前中に学んだod
コマンドでバイナリを眺める。
$ cat a.bash | od -bcx 0000000 357 273 277 043 041 057 142 151 156 057 142 141 163 150 012 012 357 273 277 # ! / b i n / b a s h \n \n bbef 23bf 2f21 6962 2f6e 6162 6873 0a0a 0000020 145 143 150 157 040 110 145 154 154 012 e c h o H e l l \n 6365 6f68 4820 6c65 0a6c 0000032
先頭に3バイトと言えばBOM(Byte Order Mark)である。
BOM を消しつつ(tr
で制御文字を消して)実行。
$ cat a.bash | tr -cd '[[:print:]][[:space:]]' | sh Hell
b.bash
od
コマンd(ry
$ cat b.bash | od -bcx 0000000 043 041 057 142 151 156 057 142 141 163 150 012 012 154 163 040 # ! / b i n / b a s h \n \n l s 2123 622f 6e69 622f 7361 0a68 6c0a 2073 0000020 313 234 057 012 313 234 / \n 9ccb 0a2f 0000024
チルダの文字コードが明らかにおかしい。
これまた午前中に知ったbash
のエスケープ展開で消して置換する。
$ cat b.bash | tr -d $'\x9c' | tr $'\xcb' '~' #!/bin/bash ls ~/
A6
拡張正規表現を正規表現で基本正規表現に変換する。
x+
をxx*
に、{x}
を展開する課題。
前からsed
で全部置換する。
繰り返しはsed
ではできないので、コマンドを作ってシェルに投げる。
$ cat extended | sed -E 's/(\[.*\]|.)\+/\1\1*/g' | sed -E 's/\((.*)\)\{(.*)\}/`yes \1 | head -\2 | tr -d " \\n"`/g' | sed -E 's/(.)\{(.*)\}/`yes \1 | head -\2 | tr -d " \\n"`/g' | sed 's/^/echo /' | bash aa*hhhhhhohohohohohohohohoho[0-9][0-9]*
Perl すごい↓
Q6 % perl -pe 's/(?:\((.+?)\)|(.))\{(\d+)\}/($1||$2)x$3/eg;s/(\[.+\]|.)\+/$1$1*/g' extended
— eban (@eban) 2016年2月13日
aa*hhhhhhohohohohohohohohoho[0-9][0-9]*#シェル芸
A7
各段落の文字数を数える。
全角スペースが段落の開始(区切り)になっていて改行は無視して大丈夫らしいので、まず改行を消して段落ごとに分けて数えた。
$ cat text | tr -d '\n' | sed 's/ /\n/g' | awk '$0=length($0)' 15 353 103
改行文字を消さないで数えるバージョン。
$ cat text | awk '/^ /{l=0}{print $0,l+=length($0)}END{print " "}' | grep -B 1 ' ' |tr '\n' ' '|sed 's/[0-9]\+ --//g'|grep -o '[0-9]*' 16 354 104
A8
メールの添付ファイルを引っこ抜く。
less
でだらーっと見てるとContent-Type: image/jpeg; name="CHINJYU.JPG"
っていうそれっぽいのが目に入る。
grep
してみるとそれっぽいのがふたつあった。
$ grep Content-Type 1350369599.Vfc03I4682c8M940114.remote Content-Type: multipart/mixed; boundary=047d7b621ee6cf83c604cc276bb3 Content-Type: text/plain; charset=ISO-2022-JP Content-Type: image/jpeg; name="CHINJYU.JPG" Content-Type: image/jpeg; name="IMG_0965.JPG"
Content-Type
のちょっと下に明らかにエンコーディングされてるデータがあったから、抜き出してデコードして見たら見えた。
$ cat 1350369599.Vfc03I4682c8M940114.remote | sed '0,/Content-Type: image\/jpeg; name="CHINJYU.JPG"/d' | sed '0,/^$/d' | sed '/^--/,$d' | base64 -d > a.jpg
おまけの環境情報
$ bash --version | grep '[0-9]\.[0-9]' GNU bash, version 4.3.42(1)-release (x86_64-unknown-linux-gnu) $ uname -a Linux host 4.4.1-2-ARCH #1 SMP PREEMPT Wed Feb 3 13:12:33 UTC 2016 x86_64 GNU/Linux $ sed --version | grep '[0-9]\.[0-9]' sed (GNU sed) 4.2.2 $ awk --version | grep '[0-9]\.[0-9]' GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.3-p5, GNU MP 6.1.0) $ grep --version | grep '[0-9]\.[0-9]' grep (GNU grep) 2.22 $ yaourt -Si coreutils | grep 'Version' # tr, ls, cat とか Version : 8.25-1 $ less --version | grep 'less [0-9]' less 481 (PCRE regular expressions) $ iconv --version | grep '[0-9]\.[0-9]' iconv (GNU libc) 2.22 $ xargs --version | grep '[0-9]\.[0-9]' xargs (GNU findutils) 4.4.2 $ cal --version | grep '[0-9]\.[0-9]' cal from util-linux 2.27.1