Just another Ruby porter,


2月中旬の日記 | RDF

2017-02-15 (Wed)

第27回シェル芸勉強会を #Vimシェル芸 で

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は用意されてるとか?


2017-02-11 (Sat)

第27回シェル芸勉強会

今回はリモート参戦。
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

2017-02-01 (Wed)

上旬


2017-01-21 (Sat)

下旬


2017-01-11 (Wed)

中旬


2月中旬の日記 | RDF


WWW を検索 jarp.does.notwork.org を検索

わたなべひろふみ
Key fingerprint = C456 1350 085F A320 C6C8 8A36 0F15 9B2E EB12 3885
Valid HTML 4.01!