Ansatzの備忘録

勉強したことあるいはふと思い立ったこと

シェルワンライナー160本ノック問題11

問題11 議事録の整理

問題のファイルは

https://github.com/shellgei/shellgei160

からダウンロードできる。

議事録の整理、つまり置換と改行を同時にやる問題だった。できたと思ったらできていなかった、結構悔しい。

先に正解を載せておく。

cat gijiroku.txt | xargs -n2 | sed 's/^すず/鈴木/;s/^さと/佐藤/;s/^やま/山田/;s/ /:/;s/$/\n/'

xargs はコマンドを指定しなければ echo を実行する。引数の個数を -n2 で2個に指定して入力ファイルを2行ずつ受け付けて echo で議事録の中身を出力しなおしている。あとは sed で適当に置換すれば完成する。

最初自分がやろうとしていたのは

cat gijiroku.txt | sed 's/^すず/鈴木/;s/^さと/佐藤/;s/^やま/山田/' | sed -r 's/^(..)\n(.*)/\1:\2/'

で、正規表現で改行を指定して後方参照で処理できないかと考えていた。実行はできるが何も変化が見えず、名字が漢字に置換されて終わっていた。

調べたところ、sed は改行で区切られたテキスト単位ごとに処理を実行するため単純に \n を入れたのではだめらしい。というわけで -z を加えて

cat gijiroku.txt | sed 's/^すず/鈴木/;s/^さと/佐藤/;s/^やま/山田/' | sed -r -z 's/^(..)(\r\n|\n|\r)(.*)/\1:\3/g'

とやってみたが最初の行しか正しく処理されず、ますますわからなくなった。

しばらく考えて、-z の処理がどうなってるか思い起こしてみたらやっとわかった。 sed で -z を指定すると改行文字が \n ではなくヌル文字になる。そのためこの問題で扱っている入力ファイルが一行の入力として扱われるようになり、g を末尾にくっつけてもうまく処理がいかないわけだ。g は全行に処理を行う命令だが、一行しかないことになっているのでこんなものをつけても意味がない。

結局この方向で考えてもわかりやすいワンライナーはかけそうにないのでやめておくことにした。