ふと、特定の文字列同士を入れ替える(パターンに応じて文字列の置換をさせる)処理をワンライナーでさせるにはどうすればいいかなと思ったので、ちょっと調べてみた。
sedの場合
sedの場合、よく思いつくのが以下の様に一度別の文字列に置換してから処理をするやり方。
コマンド | sed 's/パターンA/\x0/g;s/ぱたーんB/パターンA/g;s/\x0/ぱたーんB/g'
blacknon@BS-PUB-UBUNTU-01:~$ echo -e "「あいうえお」と「かきくけこ」\nそして、「かきくけこ」と「ABCDE」、「あいうえお」"
「あいうえお」と「かきくけこ」
そして、「かきくけこ」と「ABCDE」、「あいうえお」
blacknon@BS-PUB-UBUNTU-01:~$ echo -e "「あいうえお」と「かきくけこ」\nそして、「かきくけこ」と「ABCDE」、「あいうえお」" | sed 's/あいうえお/\x0/g;s/かきくけこ/あいうえお/g;s/\x0/かきくけこ/g'
「かきくけこ」と「あいうえお」
そして、「あいうえお」と「ABCDE」、「かきくけこ」
ただ、これだと1クッション置くために置換した文字列が含まれていた場合に考えていた出力結果が得られない。 で、他の方法について模索し、置換する際にbashのコードを生成して、それを利用する方法について思いついた。
コマンド | sed -r 's/(パターンA|ぱたーんB)/$([ "\1" == "パターンA" ] \&\& printf ぱたーんB || printf パターンA)/g;s/^/echo /g' | bash
blacknon@BS-PUB-UBUNTU-01:~$ echo -e "「あいうえお」と「かきくけこ」\nそして、「かきくけこ」と「ABCDE」、「あいうえお」"
「あいうえお」と「かきくけこ」
そして、「かきくけこ」と「ABCDE」、「あいうえお」
blacknon@BS-PUB-UBUNTU-01:~$ echo -e "「あいうえお」と「かきくけこ」\nそして、「かきくけこ」と「ABCDE」、「あいうえお」" | sed -r 's/(あいうえお|かきくけこ)/$([ "\1" == "あいうえお" ] \&\& printf かきくけこ || printf あいうえお)/g;s/^/echo /g' | bash
「かきくけこ」と「あいうえお」
そして、「あいうえお」と「ABCDE」、「かきくけこ」
perlの場合
perlの場合、どうやらパターン置換の機能があるようで、それを利用することで同様の処理が行えるようだ。
echo ABCDEと123とABCそしてABCDE | perl -pe 's/ABCDE|123/{ABCDE=>123,123=>ABCDE}->{$&}/ge'#シェル芸
— eban (@eban) 2018年4月28日
コマンド | perl -C -ple 's/パターン1|pattern2/{"パターン1"=>"pattern2","pattern2"=>"パターン2"}->{$&}/ge'
blacknon@BS-PUB-UBUNTU-01:~$ perl -le 'print {"ABCDE"=>"123","123"=>"ABCDE"}->{"123"}'
ABCDE
blacknon@BS-PUB-UBUNTU-01:~$ perl -le 'print {"ABCDE"=>"123","123"=>"ABCDE"}->{"ABCDE"}'
123
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ echo -e "ABCDEと123、ABCDE\nそして123、ABC、ABCDE"
ABCDEと123、ABCDE
そして123、ABC、ABCDE
blacknon@BS-PUB-UBUNTU-01:~$ echo -e "ABCDEと123、ABCDE\nそして123、ABC、ABCDE" | perl -C -ple 's/ABCDE|123/{"ABCDE"=>"123","123"=>"ABCDE"}->{$&}/ge'
123とABCDE、123
そしてABCDE、ABC、123
この方法なら、3パターン以上の置換も簡単に書ける。
rubyの場合
rubyの場合はもっとシンプルで、gsubでPerlと同様の処理が書けるようだ。
コマンド | ruby -pe 'gsub(/パターン1|pattern2/,"パターン1"=>"pattern2","pattern2"=>"パターン1")'
blacknon@BS-PUB-UBUNTU-01:~$ echo -e "ABCDEと123、ABCDE\nそして123、ABC、ABCDE"
ABCDEと123、ABCDE
そして123、ABC、ABCDE
blacknon@BS-PUB-UBUNTU-01:~$ echo -e "ABCDEと123、ABCDE\nそして123、ABC、ABCDE" | ruby -pe 'gsub(/ABCDE|123/,"ABCDE"=>"123","123"=>"ABCDE")'
123とABCDE、123
そしてABCDE、ABC、123