【问题标题】:How can I write multiple lines in expect program for the spawn command?如何在期望程序中为 spawn 命令编写多行?
【发布时间】:2023-03-25 04:53:01
【问题描述】:

我编写了这个小脚本,用于从远程服务器获取多个文件到我的主机:

#! /usr/bin/expect -f

spawn scp \
user@remote:/home/user/{A.txt,B.txt} \
/home/user_local/Documents
expect "password: "
send "somesecretpwd\r"
interact

这工作正常,但是当我想在文件之间创建新行时:

user@remote:/home/user/{A.txt,\
B.txt} \

我收到以下错误:

scp: /home/user/{A.txt,: No such file or directory
scp: B.txt}: No such file or directory

我试过了:

user@remote:"/home/user/{A.txt,\
B.txt}" \

得到:

bash: -c: line 0: unexpected EOF while looking for matching `"'
bash: -c: line 1: syntax error: unexpected end of file
cp: cannot stat 'B.txt}"': No such file or directory

或者这个:

"user@remote:/home/user/{A.txt,\
B.txt}" \

在开始时遇到同样的错误。

我怎样才能在多行中编写文件,但这样程序才能正常工作?我需要这个来提高所选文件的可读性。

编辑: 只将本地用户名改为user_local

【问题讨论】:

  • 我建议使用sshpass
  • sshpass 的问题是我必须为多跳传递复杂的参数(我必须至少连续使用两次 ssh)。

标签: bash expect scp


【解决方案1】:

在 Tcl(以及 Expect)中,\<NEWLINE><SPACEs> 将被转换为一个 <SPACE>,因此您不能将不包含空格的字符串写入多行。

% puts "abc\
        def"
abc def
% puts {abc\
        def}
abc def
%

【讨论】:

  • 啊,很好的解释。要仅发送带有可读代码的期望脚本的某些特定文件,我可以编写另一个脚本(例如在 python 中)来创建所需的期望脚本。也可以,例如"\n\n" 结果为 ""?
  • \<NEWLINE><SPACEs> 中的 空格 仅包括 <space>s (0x20) 和 <tab>s (0x09)。
【解决方案2】:

假设文件名真的更长(否则没什么意义),您可以使用如下几个变量:

#! /usr/bin/expect -f

set A A.txt
set B B.txt

spawn scp \
user@remote:/home/user/{$A,$B} \
/home/user/Documents
expect "password: "
send "somesecretpwd"
interact

【讨论】:

  • 对于几个文件,这可以用作临时解决方案。
【解决方案3】:

对于任何想要仅使用 expect 来解决类似问题的人:

您可以编写文件列表,然后将所有文件连接到一个字符串。

代码如下:

#! /usr/bin/expect -f

set files {\ # a list of files
A.txt\
B.txt\
C.txt\
}

# will return the concatenated string with all files
# in this example it would be: A.txt,B.txt,C.txt
set concat [join $files ,]

# self made version of concat
# set concat [lindex $files 0] # get the first file
# set last_idx [expr {[llength $files]-1}] # calc the last index from the list
# set rest_files [lrange $files 1 $last_idx] # get other files
# foreach file $rest_files {
#     set concat $concat,$file # append the concat varibale with a comma and the other file
# }
# # puts "$concat" # only for testing the output

spawn scp \
user@remote:/home/doublepmcl/{$concat} \
/home/user_local/Documents
expect "password: "
send "somesecretpwd\r"
interact

【讨论】:

  • 您可以将中间部分简化为:set concat [join $files ,] - 请参阅tcl.tk/man/tcl8.6/TclCmd/join.htm。此外,“文件”列表中条目之间的反斜杠也是多余的,因为包括换行符在内的任何空格都可用于分隔列表元素。
  • 感谢您提供较短的代码,我将在我的回答中添加此代码。
猜你喜欢
  • 2014-11-08
  • 2010-10-10
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-18
  • 2019-04-14
  • 2020-12-27
相关资源
最近更新 更多