【問題と解答】第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

イントロ

第21回シェル芸勉強会イントロ from 隆一 上田

補記

最近あまり本の宣伝をしていないのでシェルプログラミング実用テクニックから問題を持ってきました。

[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 純愛ババア学園

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
ノート   このエントリーをはてなブックマークに追加 
 

prev:【問題のみ】第21回未経験者大歓迎!誰でも働けるアットホームな職場ですシェル芸勉強会 next:GitHubのWikiの変更をHubot経由でSlackに通知

やり散らかし一覧

記事いろいろ