【問題と解答】jus共催 第30回危念シェル芸勉強会

Pocket
LINEで送る

問題のみのページはこちら

問題で使うファイル等

GitHubにあります。ファイルは

https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.30

にあります。

クローンは以下のようにお願いします。

$ git clone https://github.com/ryuichiueda/ShellGeiData.git

環境

解答例はUbuntu Linux 16.04 で作成。Macの場合はcoreutilsをインストールすると、GNUのコマンドが使えます。BSD系の人は玄人なので各自対応のこと。

イントロ

スライド

Q1

リポジトリの中に、次のようなディレクトリがあります。

$ tree posts
posts
├── 20170806_check_of_webhook
│   └── main.md
├── 20170810_negi
│   ├── green_negi.jpg
│   ├── main.md
│   ├── white_negi.jpg
│   └── ねぎ.pdf
├── 20170810_negistagram
│   └── main.md
├── 20170812_work
├── 20170812_working
│   └── main.md
├── 20170814_layout
│   └── main.md
├── 20170818_bash
│   └── main.md
├── 20170820_bootstrap
│   └── main.md
├── 20170820_injection
│   └── main.md
└── template
    └── main.md

この中の、各main.mdは次のようなヘッダ付きのマークダウンです。

$ cat posts/20170818_bash/main.md 
---
Keywords: 嫌がらせ
Copyright: (C) 2017 Ryuichi Ueda
---

# 検索機能への嫌がらせ
Keywords: ワッショイ
Keywords: ワッショイ
Keywords: ワッショイ

これらのファイルから、次のような出力を作ってください。なお、Keywordsの行は各ファイルで最初にある行しか抽出しないこととします。

20170806_check_of_webhook Keywords: Webhook
20170810_negi Keywords: ネギ
20170810_negistagram Keywords: Twitter, Instagram, ネギ
20170812_working Keywords: 働けども働けども, bashcms2
20170814_layout Keywords: table, 雑
20170818_bash Keywords: 嫌がらせ
20170820_bootstrap Keywords: Bootstrap
20170820_injection Keywords: injection
template Keywords: 

解答

grepの-mオプションを使うと一番最初にマッチした行を取り出せます。

$ grep -m 1 '^Keywords:' posts/*/main.md |
 sed 's;posts/;;' | sed 's;/main.md:; ;'

Q2

次のHTMLファイルurl.htmlについて、リンクが相対パスになっているものについては頭に/files/をつけて、/から始まっているものとhttpやhttpsから始まっているものはそのままにしてください。できる人は変なところに改行があるものなどに対応できるように、なるべく一般解に近づけましょう。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <ul>
    <li><a href="./hoge.html">ほげ</a></li>
    <li><img src="ayasii.jpg" alt="怪しい" /></li>
    <li><a href="https://blog.ueda.tech/">クソブログ</a><a href="huge.html">ふげ</a></li>
    <li><a href="/root.jpg"></a>これはそのまま</li>
    <li><a href="http://www.usptomo.com/">更新してない</a></li>
  </ul>
</body>
</html>

次が出力例です。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <ul>
    <li><a href="/files/hoge.html">ほげ</a></li>
    <li><img src="/files/ayasii.jpg" alt="怪しい" /></li>
    <li><a href="https://blog.ueda.tech/">クソブログ</a><a href="/files/huge.html">ふげ</a></li>
    <li><a href="/root.jpg"></a>これはそのまま</li>
    <li><a href="http://www.usptomo.com/">更新してない</a></li>
  </ul>
</body>
</html>

解答

いちおうこれで大丈夫だとは思うのですが、自分でもなんだかよくわかりません・・・。

$ cat url.html | sed -r 's;(img src="|a href=");&/files/;g' |
 sed -r 's;(href="|src=")/files//;\1/;' |
 sed -r 's;(href="|src=")/files/(https://|http://);\1\2;g' |
 sed 's;/./;/;g'
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <ul>
    <li><a href="/files/hoge.html">ほげ</a></li>
    <li><img src="/files/ayasii.jpg" alt="怪しい" /></li>
    <li><a href="https://blog.ueda.tech/">クソブログ</a><a href="/files/huge.html">ふげ</a></li>
    <li><a href="/root.jpg"></a>これはそのまま</li>
    <li><a href="http://www.usptomo.com/">更新してない</a></li>
  </ul>
</body>
</html>

Q3

次のファイルについて、

$ cat list
* 妬み
* 嫉み
* 僻み

次のようにHTMLにして、頭にHTTPヘッダをつけてください。インデントは不要ですがタグは1行1個でお願いします。

Content-Type: text/html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
<ul>
<li>妬み</li>
<li>嫉み</li>
<li>僻み</li>
</ul>
</body>
</html>

すぐできて退屈な人は、インターネット上のサーバでこのHTMLファイルを送信するサーバをワンライナーで立ててください。

解答

ゴリゴリやってもあまり苦労はしないと思いますが、Pandocの紹介がてら問題を出しました。

$ cat list | sed 's/\* /<li>/' | sed 's;$;</li>;' |
 sed '1iContent-Type: text/html\n\n<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><ul>'  |
 sed '$a</ul></body></html>' | sed 's/></>\n</g'
### Pandocを使う方法 ###
$ pandoc list -t html5 -s | sed '5,12d' | sed '1iContent-Type: text/html\n'

ブラウザからの応答に反応するには、レスポンス行も追加します。(改行は\r\nの方がいいかもしれません。)

$ pandoc list -t html5 -s | sed '5,12d' |
 sed '1iHTTP/1.1 200 OK\nContent-Type: text/html\n' | nc -l 8080
### 連続応答 ###
$ while : ; do pandoc list -t html5 -s | sed '5,12d' |
 sed '1iHTTP/1.1 200 OK\nContent-Type: text/html\n' | nc -l 8080 ; done

Q4

&&や;でコマンドを繋いだワンライナーで、GitHubにリポジトリを作ってそこにテキストファイルを一つ置いてください。

解答

hubの紹介のための問題でした。

$ mkdir hoge && cd hoge && git init && echo aho > aho.txt 
&& git add -A && git commit -m "aho" 
&& hub create ryuichiueda/hoge && git push origin master
Initialized empty Git repository in /home/ueda/hoge/hoge/hoge/.git/
[master (root-commit) 76206c8] aho
 1 file changed, 1 insertion(+)
 create mode 100644 aho.txt
Updating origin
created repository: ryuichiueda/hoge
Counting objects: 3, done.
Writing objects: 100% (3/3), 215 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:ryuichiueda/hoge.git
 * [new branch]      master -> master

Q5

次のファイルの1行目の複素数と2行目の複素数をかけ算してください。

$ cat complex 
1 + 4*i
3 - 2*i

解答

Perlを使ってみました。(Perlに慣れていればもっと前処理は簡単になると思います。)

$ cat complex | sed 's/^/(/' | sed 's/$/)/' | sed '2,$i*' |
 xargs | tr -d ' ' |
 xargs -I@ perl -e '{use Math::Complex;print(@);print "\n"}'
11+10i

Q6

フィボナッチ数列で、6765の4つ前の数を出力してください。

解答

$ echo a | awk 'BEGIN{a=1;b=1}{while(1){print a;c=b;b+=a;a=c}}' |
 grep -m 1 -B4 6765 | head -n 1
987

Q7

次の数字の列について、00, 01, 02,…,99の数字2つ並びのうち、含まれないものを抽出してください。できる人はループを使わないで抽出してください。

cat nums
1232154916829552629124634124821535923503018381369677458868876877570978993996890718096846698577281037379417474410221480004050608111920262721512985412925301

解答

$ seq -w 0 99 | while read n ; do grep -q $n nums || echo $n ; done 
31
33
42
43
56
61
64
65

whileやforを使わない場合はこんな感じで。

$ cat nums | sed 's/.\(.*\)/\1\n&/' | fold -b2 | grep .. | sort -u |
 sort -m - <(seq -w 00 99) | sort | uniq -u
31
33
42
43
56
61
64
65

Q8

次のアルファベットの区間のうち、間に含まれるアルファベットが一番多いものはどれでしょうか。

$ cat alphabet 
a-g
e-q
z-v
r-y

解答

ブレース展開を使うとこんな感じです。

$ cat alphabet |
 awk '{a=$1;gsub(/-/,"..",a);print "echo",$1,"{"a"}"}' |
 bash | awk '{print $1,NF}' | sort -k2,2n |
 tail -n 1 | awk '{print $1}'
e-q

あとは10進数のasciiコードに変換する方法を示します。

$ cat alphabet | xxd -ps | fold -b2| tr a-f A-F |
 sed '1iobase=10;ibase=16;' | bc | xargs -n 4 |
 awk '{print $1-$3}' | tr -d - | awk '{print NR,$1}' |
 sort -k2,2n | tail -n 1 | awk '{print $1}' |
 xargs -I@ sed -n @p alphabet 
e-q
$ cat alphabet | tr - ' ' |
 perl -anle '{print abs(ord($F[0])-ord($F[1]))}' |
 awk '{print NR,$1}' | sort -k2,2n | tail -n 1 |
  awk '{print $1}' | xargs -I@ sed -n @p alphabet 
e-q
Pocket
LINEで送る

「【問題と解答】jus共催 第30回危念シェル芸勉強会」への1件のフィードバック

コメントは停止中です。