【自習】「第58回シェル芸勉強会」の解答例

概要

  • イベント名: jus共催 第58回花粉シェル芸勉強会
  • 開催日: 2022年3月12日(土)

開催日の前日にカーラリーで使うゼッケン用ステッカーの版下を約70種類作ることになってしまったので、後日YouTubeを見ながら自習することにしました。


Q1

次のファイルmemoについて、

メモ: 2022年3月5日

* 2日後: ワクチン接種
* 6日後: 国際ロボット展
* 7日後: シェル芸勉強会

次のような出力を得てください。1行目の日付が違っても機能するワンライナーを考えてください。

* 2022年3月7日 ワクチン接種
* 2022年3月11日 国際ロボット展
* 2022年3月12日 シェル芸勉強会

A1

# 正規表現の後方参照が可能なgensub()関数を利用(gawkのみ可)して、system()関数に渡す文字列を作る
$ awk 'NR<2{gsub(/[^0-9]/,"-",$2);sub(/-$/,"",$2);D=$2}NR>2{print $1;system("date -d "gensub(/([0-9]+)日後:/,D"+\\1days +%Y年%-m月%-d日",1,$2));print $3}' memo | xargs -n3
* 2022年3月7日 ワクチン接種
* 2022年3月11日 国際ロボット展
* 2022年3月12日 シェル芸勉強会

Q2

数字を直接打ち込むことなく、date2022年02月22日 2 22:22:22と出力させてください。二列目の2は週番号です。

A2

# ${#変数名}で、変数の長さにパラメータ展開されるbashの機能を利用
$ T=WO; date -d "${#T}${#T}-${#T}-${#T}${#T} ${#T}${#T}:${#T}${#T}:${#T}${#T}" '+%x %w %T'
2022年02月22日 2 22:22:22

Q3

https://file.ueda.tech/eki/p/13.jsonのJSON形式のデータを、次のようなYAML形式に変換してください。

line:
  - line_cd: "11301"
    line_name: JR東海道本線(東京~熱海)
  - line_cd: "11302"
・・・

A3

# yqコマンドを使用
# 🔗 https://github.com/mikefarah/yq
$ yq -o xml 13.json | yq -M -p xml
line:
  - line_cd: "11301"
    line_name: JR東海道本線(東京~熱海)
  - line_cd: "11302"
    line_name: JR山手線
  - line_cd: "11303"
    line_name: JR南武線
  - line_cd: "11305"
    line_name: JR武蔵野線
  - line_cd: "11306"
(...略...)

Q4

次のような出力を得てください。

A4

# ANSIエスケープシーケンスを使い、カーソルの移動を行う
#     \033[?25l : カーソルの非表示
#     \033[?25h : カーソルの表示
#     \033[nG   : ターミナルの左端からn文字の場所に移動
awk -v c=$(tput cols) 'BEGIN{printf("\033[?25l");for(i=0;i<c-13;i++){for(j=7;j>0;j--){printf("\033[%dG💩",j*2+i-1);system("sleep 0.1")}}printf("\033[?25h\n")}'

出力は次のようになります。

A4.gif


Q5

次のファイルputinから、プーチンと読めるものの行番号を表示してください。一般解は不要ですが、行番号は直接指定しないでください。

プ-チン
プ‐チン
プーチン
プ‑チン
フ‑テン
プ−チソ
タ−チャン
プチン
プ−チン
プ–チン
プーチン
プチャーチン
プ―チン
ポ―チン
プーサン
プッチン
プチ-ン
プ—チン

A5

# nkf -Z4で全角カナを半角カナにしてから、nkf -Xで全角カナに戻してやると楽
# grep -Pのパターン内で使われている「\p{Pd}」は、ダッシュ類を示すUnicode文字プロパティ
$ nl putin | nkf -Z4 | nkf -X | grep -P '\t(プ|フ゜)(\p{Pd}|ー)チン$'
     1  プ-チン
     2  プ‐チン
     3  プーチン
     4  プ‑チン
     9  フ゜-チン
    10  プ–チン
    11  プーチン
    13  プ-チン
    18  プ-チン

Q6

次のふたつのファイルについて、

$ cat file1
バンコ
クラルンプール
ャカルタ
プノンン
$ cat file2
プンペン
アラルンプール
ンコク
ジャカタ

次の出力を得てください。行の順番は任意とします。また、完璧でなくてもよいのでなるべく一般的な解を作ってください。

バンコ ンコク
クラルンプール アラルンプール
ャカルタ ジャカタ
プノンン プンペン

A6

# あいまい検索を行うtre-agrep(agrep)を利用:
# なお、あいまい検索時に許容するエラーは2にすると上手くいく
$ cat file1 | while read l; do printf "$l "; tre-agrep -2 $l file2 | tail -n1; done
バンコ ンコク
クラルンプール アラルンプール
ャカルタ ジャカタ
プノンン プンペン

Q7

nums.gzhttps://github.com/ryuichiueda/ShellGeiData/raw/master/vol.58/nums.gz)内の数字を全て足してください。

A7

# 時間短縮のため、nums.gzについて半角数字に変換する必要がある行のみnumconvを適用する
$ (zgrep -P '^\D+$' nums.gz | numconv; zgrep -P '^\d+$' nums.gz) | awk -M '{s+=$1}END{print s}'
50000224232066
Written on March 26, 2022