シェル芸160本ノック解答例 その6

技術評論社から出版された『1日1問、半年以内に習得 シェル・ワンライナー160本ノック』の解答例です。


問題51

$ sed -E 's/^/00/;s/.*(... .*)/\1/' scores.txt | sort | join -a1 students.txt - | awk '{if(!$3)$3=0;print}'
001 井田 0
002 上田 40
003 江田 0
004 織田 0
005 加田 80
006 木田 95
007 久田 0
008 山田 76

問題52

$ awk '{if(/\*/){n=FILENAME;sub(/.*_/,"",n);for(i=1;i<NF;i++)c[i]=$(i+1)}else{for(i=1;i<NF;i++)printf "%s %s %s %d\n",n,$1,c[i],$(2+i-1)}}' data_{U,V}
U X A 4
U X B 2
U Y A 3
U Y B 1
V X A 7
V X B 6
V X C -1
V Y A 9
V Y B 8
V Y C -2

問題53

$ sort -k3,3 <(awk '{print $1,"@",$2}' devicelist.txt) <(awk '{print "@",$2,$1}' measurement.txt) | uniq -f2 --group | sed 's/^$/:/' | tr '\n' ' ' | tr : '\n' | awk '{if(NF==3){print $1,$3,$2}else{print $1,$3,$5}}' | sort
01 xxxx.0c4d.1c45 1914
02 xxxx.0d46.f3c2 @
03 xxxx.0d17.73a6 2275
04 xxxx.0d81.33b8 @
05 xxxx.0d17.9658 @
06 xxxx.0c4d.095c 3235
07 xxxx.0a69.b711 3119
08 xxxx.0d81.1da2 @
09 xxxx.0fff.d828 3618
10 xxxx.0d17.7478 3443
@ xxxx.0d81.33a8 1607
@ xxxx.17d0.2c07 3431

問題54

$ jq '.Fruits[]' fruits.json | tr '\n' @ | sed 's/}@/}\n/g' | awk '{match($3,/"(.+)",@/,n);gsub(/@/,"\n");print > n[1]".json"}'

このワンライナーを実行してfruits.jsonから書き出したJSONファイルを確認します。

$ ls
Apple.json  Banana.json  Kiwifruit.json  Mango.json  Orange.json  fruits.json

# 各JSONファイルの内容を出力
$ cat Apple.json
{
  "Name": "Apple",
  "Quantity": 3,
  "Price": 100
}
$ cat Banana.json
{
  "Name": "Banana",
  "Quantity": 6,
  "Price": 100
}
$ cat Kiwifruit.json
{
  "Name": "Kiwifruit",
  "Quantity": 40,
  "Price": 50
}
$ cat Mango.json
{
  "Name": "Mango",
  "Quantity": 100,
  "Price": 90
}
$ cat Orange.json
{
  "Name": "Orange",
  "Quantity": 15,
  "Price": 110
}

問題55

# `sed -Ez ...`以降で中間ファイルを使った場合と同じ出力が得られるように整形
$ paste -d@ <(sed '$d' watch_log.json) <(sed '1d' watch_log.json) | sed 's/\\/\\\\/g' | while read l; do diff <(echo "$l" | awk -F@ '{print $1}' | jq . | sed 's/\\n/\n/g') <(echo "$l" | awk -F@ '{print $2}' | jq . | sed 's/\\n/\n/g'); done | sed -Ez 's/2c2\n< +("timestamp": )([^,]+),\n---\n> +\1([^,]+),/diff: \2 \3/g' | awk '{if(/^[0-9]+[acd][0-9]+$/){match($0,/([0-9]+)([acd])([0-9]+)/,m);printf "%d%s%d\n",m[1]-2,m[2],m[3]-2}else{print}}'
diff: "2020-01-18 18:06:52" "2020-01-18 18:07:06"
3c3
< drwxr-xr-x+ 86 uesugi staff       2752  1 18 18:06 ..
---
> drwxr-xr-x+ 86 uesugi staff       2752  1 18 18:07 ..
diff: "2020-01-18 18:07:06" "2020-01-18 18:07:20"
2c2
< drwxr-xr-x  19 uesugi staff        608  1 12 23:22 .
---
> drwxr-xr-x  20 uesugi staff        640  1 18 18:07 .
19a20
> -rw-r--r--   1 uesugi staff          0  1 18 18:07 aaa
(...略...)

問題56

$ join -a1 <(awk -F '[:,] ' '{for(i=2;i<=NF;i++)printf "%s %s\n",$i,$1}' service_depend_list.txt | sort) <(awk -F '[:,] ' '{for(i=2;i<=NF;i++)printf "%s %s\n",$1,$i}' service_stop_weekday.txt | sort) | awk '{print $3,$2}' | sed 'y/日月火水木金土/0123456/' | sort -u | awk '{a[$1]=a[$1] ", "$2}END{for(w in a)print w,a[w]}' | sed 'y/0123456/日月火水木金土/;s/ , /: /'
日: アプリB, アプリE
月: アプリA, アプリC, アプリD
火: アプリB, アプリC, アプリE
水: アプリB, アプリC, アプリE
木: アプリA
金: アプリC, アプリD
土: アプリA, アプリB, アプリC, アプリD, アプリE

問題57

$ pandoc -t gfm table.md | sed -E 's/ ?\| ?/|/g;1h;2x;2s/[^| ]/-/g'
|AAA  |BBB|CCC|
|---  |---|---|
|1    |123|4  |
|10000|1  |64 |
|3    |3  |3  |

問題58

$ sed 's/"[^"]\+"/\n&\n/g' num.csv | sed '/^"/s/[",]//g;s/,/ /g' | xargs | tr ' ' + | bc
1235362.19999999999999999999999

問題59

$ pandoc -f csv -t plain data.csv | sed '2d' | awk '{print NR,NF}' | sort -k2,2n | uniq -uf1 | sed 's/ .*//'
4

問題60

$ dateutils.dseq -f '%F-%a' 2017-02-24 2017-12-31 | awk -F- '/Fri/{d[$1"-"$2]=$3}END{for(Ym in d)print Ym"-"d[Ym]}' | sort
2017-02-24
2017-03-31
2017-04-28
2017-05-26
2017-06-30
2017-07-28
2017-08-25
2017-09-29
2017-10-27
2017-11-24
2017-12-29

# `dateutils.dround`を利用した別解
$ echo 2017-{03..12}-01 2018-01-01 | tr ' ' '\n' | dateutils.dround -n -- -Fri
2017-02-24
2017-03-31
2017-04-28
2017-05-26
2017-06-30
2017-07-28
2017-08-25
2017-09-29
2017-10-27
2017-11-24
2017-12-29
Written on October 26, 2022