12673


unix/linux コマンドのexpectを初めて使う者です。上手く操作できないので質問させてください。

まず問題を限定するために、仮に以下の内容を持つrubyスクリプト「a.rb」を事前に用意したことにします。

[code]

    STDOUT << 'Overwrite /opt/rails/rails_app/Gemfile? (enter "h" for help) [Ynaqdh] '
    s = STDIN.gets
    STDOUT << s
    
[/code]

これを実行すると、プログラムはユーザーに入力を促すプロンプトを出し、入力があるとそれを表示して終わります。

[code]

    $ruby a.rb
    Overwrite /opt/rails/rails_app/Gemfile? (enter "h" for help) [Ynaqdh] #ここでユーザー入力待ちになる
    y  # 入力+Enterキー押下で、入力した内容を出力してプログラムを終了する
    
[/code]

以上のスクリプトファイルを前提に、expect を使って自動化を試みようと以下のスクリプトファイル(a.expect)を作成しました。

[code]

    spawn ruby a.rb
    expect "Overwrite /opt/rails/rails_app/Gemfile\? \(enter \"h\" for help\) \[Ynaqdh\] "
    sleep 3
    send "y\r"
    
[/code]

これを実行するとプロンプトが出た後、何も起きずにコマンド実行がタイムアウトで終了してしまいます。

[code]

    $ expect -f a.expect
    spawn ruby a.rb
    Overwrite /opt/rails/rails_app/Gemfile? (enter "h" for help) [Ynaqdh] 
    $  # <= 終了してる！
    
[/code]

明らかにスクリプト(a.expect)に問題があるのだろうとは思うのですが、正直何が悪いのかわかりません。  
エスケープしないといけない文字があるとかないとか、いくつかのサイトで見た範囲のことを、あまり意味が理解できないまま使っているからだとは思うのですが、manページを見ても要領が得られず、理解に苦しんでいます。アドバイスよろしくお願いします。


CC BY-SA 3.0
2015-07-24T02:05:41.700
12637
2015-07-25T06:01:52.490
2015-07-24T03:49:27.413
9403
9403
question
expect
expect スクリプトに間違いがあるらしいのだが、理由がわからない


まず `""` の中身は、最初に Tcl 上の文字列として処理されるので、正規表現としての `\` を使いたければ、`\\`
としないといけないでしょう。`[]` についてはすでに指摘されているとおりです。

それと、`expect` の最初の引数は、何もフラグを指定しなかった場合はいわゆる glob パターンで正規表現ではありません。それらを考慮すると
expect コマンドは

[code]

    expect -re "Overwrite /opt/rails/rails_app/Gemfile\\? \\(enter \"h\" for help\\) \\\[Ynaqdh\\] "
    
[/code]

とすれば動くと思います。

が、そもそも `""` で文字列を囲ってるのが災いしているので、文字列内で置換の発生しない `{}` の方を使って

[code]

    expect -re {Overwrite /opt/rails/rails_app/Gemfile\? \(enter "h" for help\) \[Ynaqdh\]} 
    
[/code]

とすればすっきりするでしょうし、前述の通り glob パターンが使えるので

[code]

    expect {Overwrite /opt/rails/rails_app/Gemfile\? (enter "h" for help) \[Ynaqdh]} 
    
[/code]

とすればさらに読みやすくなるでしょう。[] をエスケープするだけで正規表現が動いたのは、glob パターンとして _たまたま_ うまくいっただけだからです。

そして最後に `interact` が必要だったのは、この expect スクリプトは `send`
コマンド直後に終了してしまい、その子プロセスも終了させられたからです。


CC BY-SA 3.0
2015-07-25T02:08:05.270
12673
2015-07-25T06:01:52.490
2015-07-25T06:01:52.490
2521
2521
12637
answer