首页 > 解决方案 > 不使用通配符的预期工具不匹配换行符

问题描述

我正在编写一个脚本来使用 Expect 远程安装 linux 软件更新(使用 .bin 更新工具)。我在匹配一个块时遇到了麻烦,我尝试了一堆变体,但都没有成功。我已经让其他类似的脚本工作了,但是我使用通配符来匹配换行符,在这种情况下,我需要确保文件列表正是我所期望的,所以我不想打破使用任何可能隐藏不匹配的通配符。

有人可以看看并告诉我我做错了什么吗?

控制台输出,普通

Checking for local modifications.

List of modifications made within Jira directories.

The following provides a list of file modifications within the
atlassian-jira directory.

Modified files:
    atlassian-jira/WEB-INF/classes/seraph-config.xml
    bin/setenv.sh
    conf/server.xml
Removed files:
    (none)
Added files:
    atlassian-jira/WEB-INF/classes/crowd.properties

[Enter]

我最近尝试匹配它并发送 Enter (换行符仅添加到 Stack Overflow,不存在于脚本中

expect {*Checking for local modifications*Modified files:\r\n\tatlassian-jira/WEB-INF/classes/seraph-config.xml\r\n\tbin/setenv.sh\r\n\tconf/server.xml\r\nRemoved files:\r\n\t(none)\r\nAdded files:\r\n\tatlassian-jira/WEB-INF/classes/crowd.properties\r\n\r\n\[Enter\]}

当我expect-d标志运行时,它会打印出来:

expect: does "\r\nn\r\n\r\nChecking for local modifications.\r\n\r\nList of modifications made within Jira directories.\r\n\r\nThe following provides a list of file modifications within the\r\natlassian-jira directory.\r\n\r\nModified files:\r\n\tatlassian-jira/WEB-INF/classes/seraph-config.xml\r\n\tbin/setenv.sh\r\n\tconf/server.xml\r\nRemoved files:\r\n\t(none)\r\nAdded files:\r\n\tatlassian-jira/WEB-INF/classes/crowd.properties\r\n\r\n[Enter]\r\n" (spawn_id exp5) match glob pattern "*Checking for local modifications*Modified files:\r\n\tatlassian-jira/WEB-INF/classes/seraph-config.xml\r\n\tbin/setenv.sh\r\n\tconf/server.xml\r\nRemoved files:\r\n\t(none)\r\nAdded files:\r\n\tatlassian-jira/WEB-INF/classes/crowd.properties\r\n\r\n\[Enter\]"? no

我正在从外部 bash 脚本运行,如下所示:

#!/usr/bin/env bash
set -e

sudo expect -d << EOD
    spawn ${INSTALLER_PATH}

    expect_before timeout { exit 1 }

    expect {Match phrase} {
        send -- "\r"
    }

    ...

    expect eof

EOD

** 2021 年 4 月 5 日更新**

我尝试了@pynexj 的建议来使用""而不是{}围绕我的表达式(如下),它仍然不起作用。

新脚本

sudo expect -d << EOD
    ...
    expect "\r\nn\r\n\r\nChecking for local modifications.\r\n\r\nList of modifications made within Jira directories.\r\n\r\nThe following provides a list of file modifications within the\r\natlassian-jira directory.\r\n\r\nModified files:\r\n\tatlassian-jira/WEB-INF/classes/seraph-config.xml\r\n\tbin/setenv.sh\r\n\tconf/server.xml\r\nRemoved files:\r\n\t(none)\r\nAdded files:\r\n\tatlassian-jira/WEB-INF/classes/crowd.properties\r\n\r\n\[Enter\]\r\n" {
        send -- "\r"
    }

    expect eof

EOD

我运行了通过 Beyond Compare 收到的调试输出,打印出来的两个字符串 100% 匹配。

更新了调试输出

expect: does "\r\nn\r\n\r\nChecking for local modifications.\r\n\r\nList of modifications made within Jira directories.\r\n\r\nThe following provides a list of file modifications within the\r\natlassian-jira directory.\r\n\r\nModified files:\r\n\tatlassian-jira/WEB-INF/classes/seraph-config.xml\r\n\tbin/setenv.sh\r\n\tconf/server.xml\r\nRemoved files:\r\n\t(none)\r\nAdded files:\r\n\tatlassian-jira/WEB-INF/classes/crowd.properties\r\n\r\n[Enter]\r\n" (spawn_id exp5) match glob pattern "\r\nn\r\n\r\nChecking for local modifications.\r\n\r\nList of modifications made within Jira directories.\r\n\r\nThe following provides a list of file modifications within the\r\natlassian-jira directory.\r\n\r\nModified files:\r\n\tatlassian-jira/WEB-INF/classes/seraph-config.xml\r\n\tbin/setenv.sh\r\n\tconf/server.xml\r\nRemoved files:\r\n\t(none)\r\nAdded files:\r\n\tatlassian-jira/WEB-INF/classes/crowd.properties\r\n\r\n[Enter]\r\n"? no

两根弦相互重叠

您可以在 Stack Overflow 中横向滚动这些内容,以查看它们是否 100% 匹配:

# command output on top
\r\nn\r\n\r\nChecking for local modifications.\r\n\r\nList of modifications made within Jira directories.\r\n\r\nThe following provides a list of file modifications within the\r\natlassian-jira directory.\r\n\r\nModified files:\r\n\tatlassian-jira/WEB-INF/classes/seraph-config.xml\r\n\tbin/setenv.sh\r\n\tconf/server.xml\r\nRemoved files:\r\n\t(none)\r\nAdded files:\r\n\tatlassian-jira/WEB-INF/classes/crowd.properties\r\n\r\n[Enter]\r\n
\r\nn\r\n\r\nChecking for local modifications.\r\n\r\nList of modifications made within Jira directories.\r\n\r\nThe following provides a list of file modifications within the\r\natlassian-jira directory.\r\n\r\nModified files:\r\n\tatlassian-jira/WEB-INF/classes/seraph-config.xml\r\n\tbin/setenv.sh\r\n\tconf/server.xml\r\nRemoved files:\r\n\t(none)\r\nAdded files:\r\n\tatlassian-jira/WEB-INF/classes/crowd.properties\r\n\r\n[Enter]\r\n
# Expect expression underneath

标签: linuxbashshellcentosexpect

解决方案


\r\n在 Tcl 中,嵌入在大括号 ( ) 中的反斜杠转义字符串(如){}没有特殊含义。你应该在这里使用双引号。

$ tclsh
% puts {foo\tbar\r\n}
foo\tbar\r\n
% puts "foo\tbar\r\n"
foo     bar

%

根据 Tcl文档

  • [6] 大括号。

    如果单词的第一个字符是左大括号 ( {) 并且规则[5]不适用,则该单词将由匹配的右大括号 ( }) 终止。大括号嵌套在单词中:对于每个额外的左大括号,必须有一个额外的右大括号(但是,如果单词中的左大括号或右大括号用反斜杠引用,则在定位匹配的右大括号时不计算在内)。除了下面描述的反斜杠换行符替换之外,不会对大括号之间的字符执行任何替换,分号、换行符、右括号或空格也不接受任何特殊解释。这个词将完全由外大括号之间的字符组成,不包括牙套本身。

但请注意,当您使用双引号时。要匹配[Enter],您需要编写\\\[Enetr\\\],因为默认情况下该expect语句使用 glob 样式匹配。例如:

$ expect -c 'spawn -noecho bash -c {echo "[Enter]"}; expect eof'
[Enter]
$ expect -c 'spawn -noecho bash -c {echo "[Enter]"}; expect "\\\[Enter\\\]"; expect eof'
[Enter]
$ expect -c 'spawn -noecho bash -c {echo "[Enter]"}; expect -ex "\[Enter\]"; expect eof'
[Enter]
$

更新:

刚刚注意到您正在使用 Bash 的此处文档。然后你必须再做一级报价。

$ expect << EOF
> spawn -noecho bash -c {echo "[Enter]"}
> expect "\\\\\\[Enter\\\\\\]"
> expect eof
> EOF
[Enter]
$

或者您可以使用<< "QUOTED_STRING_HERE"

$ expect << 'EOF'
> spawn -noecho bash -c {echo "[Enter]"}
> expect "\\\[Enter\\\]"
> expect eof
> EOF
[Enter]
$

根据man bash,对于<< word

如果 word 的任何部分被引用,则分隔符是 word 上去除引号的结果,并且 here-document 中的行不展开。


推荐阅读