Newlines

我如何期望期望腳本中的換行符?

  • October 18, 2017

考慮這個互動式腳本:

#!/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 }

為什麼不匹配?如何檢測新提示的出現(完成命令)?

tl;博士添加-ex標誌。

這裡的事情是expect 更容易將復雜的參數傳遞給一些命令(expect/ interact):

接受包含在單個列表中的參數的命令(期望變體和互動)使用啟發式方法來確定列表實際上是一個參數還是多個參數。僅當列表確實表示具有多個嵌入的 \n 且它們之間具有非空白字元的單個參數時,啟發式方法才會失敗。這似乎不太可能,但是參數“-nobrace”可用於強制將單個參數作為單個參數處理。可以想像,這可以與機器生成的 Expect 程式碼一起使用。同樣, -brace 強制將單個參數作為多個模式/動作處理。

(來自expect命令的描述)如果整個expect語句的參數需要多於一行,所有的參數可以“支撐”成一個,以避免每一行都以反斜杠結束。在這種情況下,儘管有大括號,仍會發生通常的 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 月)中的啟發式如下:如果傳遞了一個參數並且在第一個非空格之前有一個換行符,則該參數被認為是多個參數支撐成一個。

在語言中,用和expect tcl引用的字元串是有區別的。您可以在 2 個範例中看到這一點:""``{}

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

您的 glob 模式{\n> }由 4 個要匹配的字元組成,但\n不會特別解釋為轉義。如果您使用模式,"\n> "您的匹配應該可以工作。或者您可以使用 flag-re代替預設的 glob 模式,這兩個字元將被正則表達式程式碼解釋為轉義,-re {\n> }.

引用自:https://unix.stackexchange.com/questions/390023