Linuxコンソール上でアルファベット順にn文字ずらした文字列を得る(シーザー暗号)
Pocket

アルファベット順にn文字ずらした文字列を生成する、いわゆるシーザー暗号(Caesar cipher)
これをLinuxコンソール上でワンライナーで作成させるには、どうすればよいのだろう?と思ったので、少し調べてみた。

とりあえず、以下のようにコマンドを実行することでアルファベットの小文字を任意の数ずらすことが可能だ。
(○にずらす数を入れる)

コマンド | tr $(printf %○s | tr ' ' '.' | tac)\a-z a-za-z # アルファベットをずらす
コマンド | tr a-z $(printf %○s | tr ' ' '.')\a-z # ずらしたのを戻す
[root@BS-PUB-CENT7-01 ~]# echo abcdefg | tr $(printf %1s | tr ' ' '.' | tac)\a-z a-za-z
bcdefgh
[root@BS-PUB-CENT7-01 ~]# echo abcdefg | tr $(printf %5s | tr ' ' '.' | tac)\a-z a-za-z
fghijkl
[root@BS-PUB-CENT7-01 ~]# echo abcdefg | tr $(printf %9s | tr ' ' '.' | tac)\a-z a-za-z
jklmnop
[root@BS-PUB-CENT7-01 ~]# echo jklmnop | tr a-z $(printf %9s | tr ' ' '.')\a-z
abcdefg
Sponsored Links

大文字も含める場合は、現時点だと後ろにもう一個trを含める方法しか思いつかなかった。

[root@BS-PUB-CENT7-01 ~]# echo aBCdEfg | tr $(printf %9s | tr ' ' '.' | tac)\a-z a-za-z | tr $(
printf %9s | tr ' ' '.' | tac)\A-Z A-ZA-Z
jKLmNop

 

なお、ROT13(13個ずらす)場合は、Pythonのライブラリがあるのでそちらで処理が可能だ。

コマンド | python -c 'print(raw_input().encode("rot13"))'
[root@BS-PUB-CENT7-01 ~]# echo ABcdEfGh | python -c 'print(raw_input().encode("rot13"))'
NOpqRsTu

 

2016/06/27 追記

他の人が考えてくれた方法があったので追記。

Linuxコンソール上でアルファベット順にn文字ずらした文字列を得る(シーザー暗号) th0x0472.log/ウェブリブログ(@th0x0472)

シーザー暗号 #シェル芸 Just another Ruby porter, 2016-6-c(@eban)

特に、某界隈(だけでなく)で有名なebanさんの解き方が…
こんな短くできたんだ…

tacの意味がよくわからない。あとtrで空白を”.”に変換しているのも不要のような。

$ echo abcdefg | tr “$(printf %1sA-z)” A-zA-z
bcdefgh
$ echo aBCdEfg | tr “$(printf %9sA-z)” A-zA-z
jKLmNop

でいいのではないかな。大文字が含まれていてもいける。

$ echo bcdefgh | tr A-z “$(printf %1sA-z)”
abcdefg
$ echo jKLmNop | tr A-z “$(printf %9sA-z)”
aBCdEfg

 

空白でいけたとは…
復号化も簡単にかけられる様子。

[root@BS-PUB-CENT7-01 ~]# # 暗号化
[root@BS-PUB-CENT7-01 ~]# echo aBcDeFg | tr "$(printf %1sA-z)" A-zA-z
bCdEfGh
[root@BS-PUB-CENT7-01 ~]# # 復号化
[root@BS-PUB-CENT7-01 ~]# echo aBcDeFg | tr "$(printf %1sA-z)" A-zA-z | tr A-z "$(printf %1sA-z)"
aBcDeFg

 

2016/06/28 追記

シーザー暗号 #シェル芸 Just another Ruby porter, 2016-6-c(@eban)

@ebanさんの昨日の方法だと、A-zがA-Za-zという扱いになるので、Zを一文字ずらすと小文字のaになってしまい想定の動作にならないというのがあったらしい。
で、さらに改良が加えられていた。

昨日のはzがAになったりといろいろとダメダメだったの出直し。
1つずらす場合は
tr a-zA-Z b-zaB-ZA
となればいいわけだが、1からこの文字列を作るのは難しい。そこで
abcdefghijklmnopqrstuvwxyz

bcdefghijklmnopqrstuvwxyza
に変換することにする。これはsedなら簡単だ。
$ printf %s {a..z} | sed -E ‘s/^(.{1})(.*)/\2\1/;s/.*/&\U&/’
bcdefghijklmnopqrstuvwxyzaBCDEFGHIJKLMNOPQRSTUVWXYZA
というわけで大文字も含んだ形で完成。
$ echo aBCdEfgXyZ | tr a-zA-Z “$(printf %s {a..z} | sed -E ‘s/^(.{9})(.*)/\2\1/;s/.*/&\U&/’)”
jKLmNopGhI
$ echo jKLmNopGhI | tr “$(printf %s {a..z} | sed -E ‘s/^(.{9})(.*)/\2\1/;s/.*/&\U&/’)” a-zA-Z
aBCdEfgXyZ
でも、ちょっとださい。

 

そんな方法が…
上の@ebanさんの方法、sedで置換するアルファベットの順番を入れ替えてるのがキモなので、自分の中に落とし込むために整理する。

[test@BS-PUB-CENT7-01 ~]$ # printfでa~zまでを出力させる。
[test@BS-PUB-CENT7-01 ~]$ # ※echoでブレース展開すると間に空白が入るので、printfで出している(ここでは最後に改行が入るためのechoしている)。
[test@BS-PUB-CENT7-01 ~]$ echo $(printf %s {a..z})
abcdefghijklmnopqrstuvwxyz
[test@BS-PUB-CENT7-01 ~]$
[test@BS-PUB-CENT7-01 ~]$ # sedでアルファベットの位置を入れ替えている。「^(.{3})」で、行頭から数えて○文字(とりあえず3文字にしている)を指定している。
[test@BS-PUB-CENT7-01 ~]$ # このとき、拡張正規表現で()内で指定しているものは、\1、\2で指定でき るので、それの位置を入れ替えてやる。
[test@BS-PUB-CENT7-01 ~]$ echo $(printf %s {a..z}) | sed -E 's/^(.{3})(.*)/\2\1/'
defghijklmnopqrstuvwxyzabc
[test@BS-PUB-CENT7-01 ~]$ echo $(printf %s {a..z}) | sed -E 's/^(.{3})(.*)/\2/'
defghijklmnopqrstuvwxyz
[test@BS-PUB-CENT7-01 ~]$ echo $(printf %s {a..z}) | sed -E 's/^(.{3})(.*)/\1/'
abc
[test@BS-PUB-CENT7-01 ~]$
[test@BS-PUB-CENT7-01 ~]$ # アルファベットの位置を入れ替えたものに対し、大文字変換したものを追 加する。
[test@BS-PUB-CENT7-01 ~]$ echo $(printf %s {a..z}) | sed -E 's/^(.{3})(.*)/\1/;s/.*/&\U&/'
abcABC
[test@BS-PUB-CENT7-01 ~]$ echo $(printf %s {a..z}) | sed -E 's/^(.{3})(.*)/\2\1/;s/.*/&\U&/'
defghijklmnopqrstuvwxyzabcDEFGHIJKLMNOPQRSTUVWXYZABC

 

Pocket

Written by blacknon

インフラ系のSE。一時期はプログラマ。 仮想化とオープンソースに興味あり。一日中寝てたい今日このごろ。 スペインとかで働きたいなぁ…(シエスタがあるので)

This article has 1 comments

  1. Pingback: sedで文字列を横にn文字ずらしていく(スライドしていく) | 俺的備忘録 〜なんかいろいろ〜

Leave a Comment

メールアドレスが公開されることはありません。