スクリプトに改行文字がどのように表示されると予想しますか?

スクリプトに改行文字がどのように表示されると予想しますか?

次の対話型スクリプトを検討してください。

#!/usr/bin/env bash
set -eu
while true; do
    read -p '> '
    if [ "$REPLY" == quit ]; then
        break
    fi
    echo "'$REPLY'"
done

expect今私はそれと対話したいと思います:

#!/usr/bin/env bash
set -eu
echo '
    spawn ./1.sh
    expect >
    send cmd1\n
    expect {\n> }
    send quit\n
' | expect -d

しかし、実行すると、次のように表示されます。

...
expect: does " cmd1\r\n'cmd1'\r\n> " (spawn_id exp6) match glob pattern "\n> "? no
expect: timed out
send: sending "quit\n" to { exp6 }

なぜ一致しないのですか?新しいプロンプト(コマンド完了)の出現をどのように検出しますか?

答え1

言語では、expect tcl文字列の使用と引用には違いがあります。次の2つの例でこれを確認できます。""{}

$ expect -c 'puts "a\nb"'
a
b
~ $ expect -c 'puts {a\nb}'
a\nb

globパターンは、一致{\n> }するが\n特別にエスケープされたと解釈されない4つの文字で構成されています。パターンを使用すると、"\n> "一致が機能します。あるいは、デフォルトのglobパターンの代わりにフラグを使用する-reこともでき、両方の文字は正規表現コードによってエスケープ文字として解釈されます-re {\n> }

答え2

長すぎます。ロゴを追加してください-ex

ここで重要なのはexpect 仕事を簡単にしましょういくつかのコマンド(expect/ interact)に複雑なパラメータを渡します。

単一のリストに含まれる引数(バリアントとインタラクションの予測)を許可するコマンドは、経験的な方法を使用して、リストが実際に1つの引数であるか複数の引数であるかを決定します。リストが実際に単一の引数を表し、その引数の間に空白以外の文字を含む\ nが複数含まれている場合にのみ、経験的方法は失敗します。そうではありませんが、「-nobrace」パラメータを使用すると、個々の引数を単一の引数として扱うように強制できます。おそらく、これはマシンで生成されたExpectコードで使用できます。同様に、-braceは単一の引数が複数のモード/タスクで処理されるように強制します。

(expectコマンドの説明で)Expectステートメント全体のパラメータに複数の行が必要な場合は、各行がバックスラッシュで終わるのを防ぐために、すべてのパラメータを1行に「中括弧」で囲むことができます。この場合、中括弧にもかかわらず、一般的なTcl置換が依然として発生します。

ここで例を見てみましょう。

#!/usr/bin/env bash
set -eu
f() {
    echo line 1
    sleep 1
    echo line 2
}
export -f f
echo '
    spawn bash -c f
    expect {
        {line 1} {puts 1}
        {line 2} {puts 2}
    }
    expect \
        {line 1} {puts 1} \
        {line 2} {puts 2}
' | expect

出力:

spawn bash -c f
line 1
1
line 2
2

私が見つけたリポジトリでは、経験的最新のコミット(2014年5月)では、次のようになります。次のように:引数が渡され、最初の非空白文字の前に改行文字がある場合、引数は1つに囲まれた複数の引数と見なされます。

関連情報