Q1 GNU sedと同じ。
% echo abcdefghijklmn | ex /dev/stdin +'s/\(.\)\(.\)/\1\u\2/g|p|q!' aBcDeFgHiJkLmN % echo abcdefghijklmn | vim -es /dev/stdin +'s/../\u&/g|p|q!' AbCdEfGhIjKlMn
文字単位の移動も簡単にできるので、ブレース展開との合わせ技で。
% echo abcdefghijklmn | vim -es /dev/stdin +'norm l~'{,,,,,,} +'p|q!' aBcDeFgHiJkLmN % echo abcdefghijklmn | vim -es /dev/stdin +'norm ~l'{,,,,,,} +'p|q!' AbCdEfGhIjKlMn
Q2 FizzBuzz
% vim -es +$'norm 33o\nFizz\n\e' +$'let @a="ABuzz\e5k"|norm 20@a' +'%s/^$/\=line(".")/|%p|q!' 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz <以下略>
normだとなぜかqでのマクロが保存できないので苦肉の策。直接レジスタに入れてる。
行って帰って間を埋める。生のESC等は扱い辛いので$''で表現。
Q3 3move7
% seq 1 10 | vim -es /dev/stdin +'3m7|%p|q!' 1 2 4 5 6 7 3 8 9 10
実にvim向きの問題。
Q4 aho.cc
% cat aho.cc | vim -es /dev/stdin +'/main/,/^}/m$|%p|q!' | g++ -xc++ -; ./a.out aho
これもmove一発。Q3と同じ。
Q5 偶奇入れ替え
% seq 10 | vim -es /dev/stdin +1 +'m+1|+1'{,,,,} +'%p|q!' 2 1 4 3 6 5 8 7 10 9
奇数行でm+1を実行すると現在行と次行が入れ替わるので、さらに次行に移動(+1)し、
ブレース展開で5回繰り返し。
Q6 階段状
% echo 1 | vim -es /dev/stdin +'for i in range(10)|p|s/./&&/|endfor|q!' 1 11 111 1111 11111 111111 1111111 11111111 111111111 1111111111
p|s/./&&/を10回繰り返し。ブレース展開技でもいけそうだが、
vimのわけのわからない制限により10個までしか指定できない。
% echo 1 | vim -es /dev/stdin +'p|s/./&&/'{1..10} +'q!' VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Nov 24 2016 22:32:42) Too many "+command", "-c command" or "--cmd command" arguments More info with: "vim -h"
Q7 縛り1 使うコマンドはseq、cp、vimだけ
% rm a* % vim -es +'wq a' % seq 10 | vim -es /dev/stdin +'g/^/exe "!cp a a" . getline(".")' +'q!' % ls a a1 a10 a2 a3 a4 a5 a6 a7 a8 a9
Q7 縛り2 ワンライナー中で数字を使わない
実はgetline(".")をline(".")に変更すれば行番号が使えるので、
なんでもいいので10行作ればいい。
% rm a* % vim -es +'wq a|norm Yppppppppp' +'g/^/exe "!cp a a" . line(".")' +'q!' % ls a a1 a10 a2 a3 a4 a5 a6 a7 a8 a9
ついでにseq 10相当をvimで。
% vim -es +'norm Yppppppppp' +'%#|q!' 1 2 3 4 5 6 7 8 9 10
微妙に違うのでちょっとがんばってみた。
% vim -es +'norm Yppppppppp' +'%s/^/\=line(".")' +'%p|q!' 1 2 3 4 5 6 7 8 9 10
Q8 山
% echo 1 | vim -es /dev/stdin +'t.|s/./&&'{,,,} +'g/^/t5' +'%p|q!' 1 11 111 1111 11111 11111 1111 111 11 1
tはcopyの別名。cはchangeなのでcopyは短縮形でもcoと書かないといけないが、
1文字で書きたい人のためにtは用意されてるとか?
今回はリモート参戦。
sedのtがどーのこーのとあったので、Q6をtを使って解く。
bはgotoでtはsでの置き換えが成功したら飛ぶというだけなので、
まあ、そんな難しい話でもない。
sの成功フラグはtやTで飛ぶか次のサイクルへ移行したらOFFになる。
まずはbを使った場合。
% echo 1 | sed ':a;p;s/./&&/;/.\{10\}/!b a' 1 11 111 1111 11111 111111 1111111 11111111 111111111 1111111111
9回繰り返すだけだ。10回じゃないのはデフォルトの出力が最後にあるため。
1と限定できればs/^/1/と短く書けるが、
echo aとか任意の文字でもいいようにしている。
これを踏まえて、tを使うようにする。
sのパターンで10個以上になったらmatchしないようにしてやればいいだけ。
% echo 1 | sed -nr ':a;p;s/^(.){1,9}$/&\1/;t a' 1 11 111 1111 11111 111111 1111111 11111111 111111111 1111111111
\があると見辛いので-rを使った。
/^(.){1,9}$/とすることで1から9文字のときだけmatchする。
9回繰り返すという意味では例のブレース展開技も使える。
% echo 1 | sed -e'p;s/./&&/;#'{1..9} 1 11 111 1111 11111 111111 1111111 11111111 111111111 1111111111