39264


%x() の構文を使って、コマンドを実行してみようとしました。

構文の中身は、基本的にはただのシェルスクリプトですが、シェルとして書いた場合にパーセントの文法とぶつかって意図しない動作が引き起こされたらいやだな、と考えています。

質問:

  * パーセント記法の中の文法 (syntax 的な仕様) について記述されている資料などはありますか？


CC BY-SA 3.0
2017-11-03T02:10:42.297
39261
2017-11-03T07:55:29.340
754
question
ruby
ruby のパーセント記法の文法はどうなっている？


Ruby 2.4.0 リファレンスマニュアルの[「%記法」](https://docs.ruby-
lang.org/ja/2.4.0/doc/spec=2fliteral.html#percent)に以下のとおり書いてあります
(一部省略して引用します)。

> **`%x!STRING!` : コマンド出力**  
>  !の部分には改行を含めた任意の非英数字を使うことができます。
> 始まりの区切り文字が括弧(`(`,`[`,`{`,`<`)である時には、終りの区切り文字は
> 対応する括弧になります。括弧を区切り文字にした場合、対応が取れていれば 区切り文字と同じ括弧を要素に含めることができます。

`STRING` と書かれている部分について、[「コマンド出力」](https://docs.ruby-
lang.org/ja/2.4.0/doc/spec=2fliteral.html#command)のドキュメントには「(``command``
形式の他に) %記法による別形式のコマンド出力もあります」と書かれているので、おそらく Ruby の[文字列リテラル](https://docs.ruby-
lang.org/ja/2.4.0/doc/spec=2fliteral.html#string)の中身と同じなのだと思います。つまり、`%x()`
の中身では `\n` などのバックスラッシュ記法や `#{variable}` などの式展開が行えるようになっています。


CC BY-SA 3.0
2017-11-03T02:33:25.003
39263
2017-11-03T07:55:29.340
2017-11-03T07:55:29.340
19110
19110
39261
answer


[%記法](https://docs.ruby-lang.org/ja/latest/doc/spec=2fliteral.html#percent)である

[code]

    %x(コマンドの文字列)
    
[/code]

は[コマンド記法](https://docs.ruby-
lang.org/ja/latest/doc/spec=2fliteral.html#command)である

[code]

    `コマンドの文字列`
    
[/code]

の別の記述方法に過ぎません。コマンド記法と同じく **バックスラッシュ記法** や **式展開**
が行われます。「`」の場合との違いは「`」自身があらわれるときに`\`でエスケープする必要が無いと言うことです。代わりに、枠の終端である「)」は対応する「(」がない場合はエスケープする必要があります。他、枠として使う記号は変更でき、それぞれ対応する物に対してエスケープが必要になる場合があります。

[code]

    str = 'hoge'
    `(echo #{str};\n [ "#{str}" = "hoge" ] && echo #{str}_\`date +%Y%m%d\` ')]}!')`
    %x((echo #{str};\n [ "#{str}" = "hoge" ] && echo #{str}_`date +%Y%m%d` '\)]}!'))
    %x[(echo #{str};\n [ "#{str}" = "hoge" ] && echo #{str}_`date +%Y%m%d` ')\]}!')]
    %x{(echo #{str};\n [ "#{str}" = "hoge" ] && echo #{str}_`date +%Y%m%d` ')]\}!')}
    %x!(echo #{str};\n [ "#{str}" = "hoge" ] && echo #{str}_`date +%Y%m%d` ')]}\!')!
    
[/code]

上は全て同じです。`()`等は対応するカッコが組になっているときはエスケープの必要が無い(してはいけない)ことに注意してください。組になっていない所はエスケープする必要があります。


CC BY-SA 3.0
2017-11-03T06:07:39.213
39264
2017-11-03T06:07:39.213
7347
39261
answer