【問題と解答】第21回未経験者大歓迎!誰でも働けるアットホームな職場ですシェル芸勉強会
Sat Feb 13 16:53:16 JST 2016 (modified: Sun Oct 1 10:50:27 JST 2017)
views: 3051, keywords:コマンド,CLI,Linux,UNIX/Linuxサーバ,USP友の会,シェル芸,シェル芸勉強会 この記事は最終更新日が7年以上前のものです。
問題で使うファイル等
GitHubにあります。ファイルは
https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.21
にあります。
クローンは以下のようにお願いします。
git clone https://github.com/ryuichiueda/ShellGeiData.git $
環境
今回はUbuntu Linuxで解答例を作りましたので、BSD系、Macな方は以下の表をご参考に・・・。
Mac,BSD系 | Linux |
---|---|
gdate | date |
gsed | sed |
tail -r | tac |
gtr | tr |
gfold | fold |
イントロ
補記
最近あまり本の宣伝をしていないのでシェルプログラミング実用テクニックから問題を持ってきました。
[amazonjs asin="4774173444" locale="JP" title="シェルプログラミング実用テクニック (Software Design plus)"]
Q1
ShellGeiData/vol.21/Q1のbba.pdfからテキストを抽出して標準出力に出してください。
解答例
例題のファイルの日本語にはFlateDecodeという圧縮がかかっていますが、これを解凍する一般的なコマンドは見つかりませんでした。ですのでpdf用のコマンドを紹介するだけで・・・。FlateDecodeの解凍コマンドはzlibを使うと自作はできる模様。
###poppler-utilsをインストール###
sudo apt-get install poppler-utils
$ ###あとはlessとかpdftotextとか###
less bba.pdf | cat
$
群馬のシャブばばあ
hoge.txt[2016/02/09 22:30:32]
pdftotext -q bba.pdf -
$
群馬のシャブばばあ
hoge.txt[2016/02/09 22:30:32]
Q2
次のデータはShift JIS(cp932)の固定長データです。
cat anydata.cp932
$ 00000001??ӹ?ݺ?*******214413051100000002ʰ????ݸ*********114413018800000003???ӷ?ݺ?********210413093100000004??ݷ?ݺ?*********234413000800000005???ް??׳???ݺ?331413090000000006??Э????ݾ??ݺ?1234130981
次のようなUTF-8のテキストに変換してください。
00000001ハナモゲギンコウ*******2144130511
00000002ハードバンク*********1144130188
00000003コドモギンコウ********2104130931
00000004ハタンギンコウ*********2344130008
00000005アンダーグラウンドギンコウ3314130900
00000006バミューダメンゼイギンコウ1234130981
解答
###Shift JISの半角は1バイトなのでUTF-8に変換する前に折り返すと楽です。###
cat anydata.cp932 | fold -b35 | nkf -wLux
$ 00000001ハナモゲギンコウ*******2144130511
00000002ハードバンク*********1144130188
00000003コドモギンコウ********2104130931
00000004ハタンギンコウ*********2344130008
00000005アンダーグラウンドギンコウ3314130900
00000006バミューダメンゼイギンコウ1234130981
###1行の長さを調べるときは仕様書を見るか、規則性を見つけて折り返して長さを調べる###
cat anydata.cp932 | sed 's/[0-9]\\{10\\}/&\\n/g' |
$ LANG=C awk '{print length($0)}'
35
35
35
35
35
35
1
1
Q3
2016年の日曜日を全て列挙してください。
解答
GNU dateの-fを使うと楽です。
seq 20160101 20161231 | date -f - 2> /dev/null | grep 日曜日
$ 2016年 1月 3日 日曜日 00:00:00 JST
2016年 1月 10日 日曜日 00:00:00 JST
2016年 1月 17日 日曜日 00:00:00 JST
...
2016年 12月 18日 日曜日 00:00:00 JST
2016年 12月 25日 日曜日 00:00:00 JST
###Tsukubaiを使う例###
mdate -e 20160101 20161231 | tr ' ' '\\n' | yobi 1 | awk '$2==0'
$ 20160103 0
20160110 0
20160117 0
...
20161218 0
20161225 0
Q4
次のデータファイル
001 あみだばばあ
002 砂かけばばあ
003 ******
004 尾崎んちのババア
に、次の新しいデータ
002 *******
003 群馬のシャブばばあ
005 純愛ババア学園
を反映して
001 あみだばばあ
002 *******
003 群馬のシャブばばあ
004 尾崎んちのババア
005 純愛ババア学園
というデータを出力してください。
解答
sort -ms -k1,1 newdata data | uniq -w 3
$ 001 あみだばばあ
002 *******
003 群馬のシャブばばあ
004 尾崎んちのババア
005 純愛ババア学園
Q4$ cat newdata data | sort -snuk1,1 #シェル芸
— 石井 久治 (@hisaharu) 2016, 2月 13
@hisaharu
— mollinaca (@syoutin) 2016, 2月 13
sort -u -k1,1 newdata data
でしたねー!勉強になります
Q5
GitHubのvol.21/Q5にある次の二つのシェルスクリプトのデバッグをしてください。
cat ./a.bash
$ #!/bin/bash
echo Hell
###実行すると変なバグ###
./a.bash
$ ./a.bash: 行 1: #!/bin/bash: そのようなファイルやディレクトリはありません
Hell
cat b.bash
$ #!/bin/bash
ls ˜/
###ホームディレクトリが表示されない###
./b.bash
$ ls: ˜/ にアクセスできません: そのようなファイルやディレクトリはありません
解答
a.bashについては「BOM付きUTF-8」という凶悪なフォーマットなので発見はバイナリの理解が大きな助けになります。が、とりあえずnkfに通せばBOMは取れます。たまにWindowsからやってきます。
###調べるとUTF-8と出るので発見が遅れる。###
nkf -g a.bash
$ UTF-8
###xxdで見ると頭に変なバイト列。###
xxd -ps a.bash
$ efbbbf23212f62696e2f626173680a0a6563686f2048656c6c0a
###ただし、見なくてもnkfで除去できる。###
nkf -wLux a.bash > a
$ chmod +x a
$ ./a
$ Hell
b.bashは、チルダがUTF-8のマルチバイト文字になっていて、~/がホームディレクトリに変換されません。このスクリプトには他にマルチバイト文字がないので、次のようなワンライナーでチルダがおかしいことを発見できます。
iconv -c -f utf-8 -t ascii b.bash | diff - b.bash
$ 3c3
< ls /
---
> ls ˜/
Q6
次の拡張正規表現をワンライナーで基本正規表現に変換してください。括弧の中の数字は数字の回数の文字列の繰り返しに展開してください。
cat extended
$ a+h{5}(ho){10}[0-9]+
解答
ゴリゴリです。
cat extended | sed 's/[+}]/&\\n/g' | sed 's/\\(.*\\)+/\\1\\1*/' |
$ tr '{}()' ' ' |
awk 'NF==2{for(i=1;i<=$2;i++){printf $1};print ""}NF==1' |
tr -d '\\n' | xargs
aa*hhhhhhohohohohohohohohoho[0-9][0-9]*
Q7
GitHubのvol.21/Q7にあるテキストについて、各段落の文字数を数えてください。
解答
改行をとって数える対象を1行にまとめる方針が簡単です。解答例はロケールが日本語で、awkがgawkである等、いろいろ制約がありますが・・・。
cat text | tr -d '\\n' | sed 's/ /\\n/g' |
$ awk '{print length($1),$1}'
0
15 恥の多い生涯を送って来ました。
353 自分には、人間の生活というものが、...にわかに興が覚めました。
103 また、自分は子供の頃、...とばかり思っていました。
Q8
GitHubのvol.21/Q8にある1350369599.Vfc03I4682c8M940114.remoteから添付ファイルを抽出して画像を復元してください。二つありますが別々に処理して構いません。
解答
まず、何行目から何行目までがデータなのか調べます。
grep -n -C 1 -- -- 1350369599.Vfc03I4682c8M940114.remote
$
(略)59:--047d7b621ee6cf83c604cc276bb3
60-Content-Type: image/jpeg; name="CHINJYU.JPG"
--
665-0000000000000000000000000000001//9k=
666:--047d7b621ee6cf83c604cc276bb3
667-Content-Type: image/jpeg; name="IMG_0965.JPG"
--
77341-xk9On61jS6VNFJqFxdoIZYbWK6QALsnJbBjHYcc4GT2IHJrGhUevkZ1MNypPuf/Z
77342:--047d7b621ee6cf83c604cc276bb3--
で、その範囲を抽出して変換します。一つめの画像の切り出しの例だけ示しておきます。
###出力の範囲を見ながらデータを切り出す###
sed -n '60,665p' 1350369599.Vfc03I4682c8M940114.remote |
$ sed -n '6,$p' | base64 -d > a.jpg
###ImageMagickのidentifyコマンドでちゃんと画像になっているか確認###
ueda@remote:~/GIT/ShellGeiData/vol.21/Q5$ identify a.jpg
a.jpg JPEG 261x261 261x261+0+0 8-bit DirectClass 34.2KB 0.010u 0:00.019
###さらにavplayで画像を見る###
avplay a.jpg $
Q8 % uudeview -i 1350369599.Vfc03I4682c8M940114.remote#シェル芸
— eban (@eban) 2016, 2月 13