11689


ROT13という簡単な換字式暗号をRubyで作ってみました。

[code]

    str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
    # ROT13
    p str.tr("A-Za-z", "N-ZA-Mn-za-m")
    p str.tr("\x41-\x5a\x61-\x7a", "\x4e-\x5a\x41-\x4d\x6e-\x7a\x61-\x6d")
    
[/code]

実行結果  
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm0123456789"  
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm0123456789"

これを次のようにダブルクォートをシングルクォートにかえると、  
下の方の出力が上手くいかないのはなぜでしょうか？  
また修正可能であるなら、どのように修正すればよろしいでしょうか？

[code]

    str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    # ROT13
    p str.tr('A-Za-z', 'N-ZA-Mn-za-m')
    p str.tr('\x41-\x5a\x61-\x7a', '\x4e-\x5a\x41-\x4d\x6e-\x7a\x61-\x6d')
    
[/code]


CC BY-SA 3.0
2015-06-24T13:09:19.897
11687
2015-06-24T14:31:56.477
2015-06-24T13:41:50.260
5363
5363
question
ruby
ROT13について


[ダブルクォートで囲まれた文字列ではバックスラッシュ記法と式展開(後述)が有効になります。](http://docs.ruby-
lang.org/ja/2.1.0/doc/spec=2fliteral.html#string)


CC BY-SA 3.0
2015-06-24T13:22:51.597
11688
2015-06-24T13:22:51.597
7471
11687
answer


シングルクォートの中ではバックスラッシュ記法が使えないため、`\`が`\`という文字そのものとして解釈されます。

そうすると`String#tr`は、`\x4e-\x5a`と`\x6e-\x7a`の`e-\`の部分を`e`から`\`までの範囲として解釈しますが、`\`のコードポイントが`e`より小さいため、不正な範囲としてエラーになります。

ドキュメントには明確に書かれていませんが、`String#tr`の範囲指定では右辺のコードポイントが左辺のコードポイント以上でなければいけないという制約があるようです。  
（a-zはOKだがz-aという逆順の指定はNG）

> 文字列はダブルクォートまたはシングルクォートで囲まれています。ダブルクォートで囲まれた文字列ではバックスラッシュ記法と式展開(後述)が有効になります。
> シングルクォートで囲まれた文字列では、 \(バックスラッシュそのもの)と \' (シングルクォート) を除いて文字列の中身の解釈は行われません。

<http://docs.ruby-lang.org/ja/2.1.0/doc/spec=2fliteral.html#string>


CC BY-SA 3.0
2015-06-24T13:25:46.747
11689
2015-06-24T13:25:46.747
3639
11687
answer


クォート方法を変えるとか。

[code]

    p str.tr(%Q(\x41-\x5a\x61-\x7a), %Q(\x4e-\x5a\x41-\x4d\x6e-\x7a\x61-\x6d))
    
[/code]

実質的にはダブルクォートと変わりませんが。


CC BY-SA 3.0
2015-06-24T14:31:56.477
11691
2015-06-24T14:31:56.477
5288
11687
answer