0


Expect交互工具与字符处理

一、免交互应用

1. Here Document

1.1 定义与语法

Here Document 是标准输入的一种替代品,使用I/O重定向的方式将命令列表提供给交互式程序 ,可以帮助脚本开发人员不必使用临时文件来构建输入信息,而是直接就地生产出一个文件并用作命令的标准输入,Here Document 可以与非交互式程序和命令一起使用。

语法格式:

命令  <<  标记
....
......
标记

1.2 注意事项

  • 标记可以使用任意的合法字符(通用的字符是EOF)
  • 结尾的标记一定要顶格写,前面不能有任何字符(包括空格)
  • 结尾的标记后面也不能有任何字符(包括空格)
  • 开头标记前后空格会被省略掉
  • 变量使用双引号

1.3 eof

示例:

使用Here Document结合重定向符号>或>>来将多行文本重定向到文件。

[root@localhost ~]# cat > file.txt << eof
> 1
> 2
> eof
[root@localhost ~]# cat file.txt 
1
2

在上面的示例中,cat > file.txt 表示将输入重定向到 file.txt 文件中。<< oef 表示开始 Here Document,eof 表示结束 Here Document。文本块中的内容会被作为输入传递给 cat 命令,并写入到 file.txt 文件中。当然 cat > file.txt << eof 也可以写成 cat << eof > file.txt。

注意也可以写成<< EOF,同时结束也要写EOF;如果不指定文件,结束后内容将打印在当前屏幕上。

如果你想追加文本到文件而不是覆盖原有内容,可以使用重定向符号 >>

[root@localhost ~]# cat >> file.txt << eof
> a
> b
> eof
[root@localhost ~]# cat file.txt 
1
2
a
b

cat >> file.txt 表示将输入追加到 file.txt 文件中,而不是覆盖原有内容。

可以根据需要自由选择文件名和分隔符。确保开始和结束的分隔符(大小写)相同,并且没有特殊含义。注意,如果结束符eof后存在空格,将没有结束功能,默认为文本内容。

应用:

使用 wc -l 命令后面直接跟文件名就可以统计文件内有多少行内容,将要统计的内容置于标记“EOF” 之间,直接将内容传给 wc -l 来统计。

[root@localhost opt]# vim wc.sh
#!/bin/bash
wc -l << EOF
line 1
line 2
EOF
[root@localhost opt]# bash wc.sh 
2

使用 passwd 命令设置密码,EOF 标记之间的两行是输入的密码和确认密码,两行内容必须保持一致,否则密码设置不成功。此脚本执行后不会输出任何信息,可另开一个终端登录用户,输入新修改的密码来验证密码是否修改正确。

[root@localhost opt]# passwd fql << eof
> 123
> 123
> eof
更改用户 fql 的密码 。
新的 密码:无效的密码: 密码少于 8 个字符
重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。

Here Document 变量设定:

Here Document 也支持使用变量,如果标记之间有变量被使用,会先替换变量值。如果想要将一些内容写入文件,除了常规的方法外,也可以使用 Here Document。如果写入的内容中包含变量,在写入文件时要先将变量替换成实际值,在结合 cat 命令完成写入。

[root@localhost opt]# name=zhangsan;age=20
[root@localhost opt]# cat << eof
> Name=$name
> Age=$age
> eof
Name=zhangsan
Age=20

定义了两个变量:name 和 age。然后,使用 Here Document 将包含这些变量值的文本传递给 cat 命令。 如果希望在Here Document中保留变量的字面值而不进行替换,可以使用单引号或双引号来括住 Here Document 的开始标记,即 cat << 'eof',在这种情况下,输出将保留 $name 和 $age 作为字面文本,而不会被替换为变量的实际值。

1.4 tee

tee 命令将标准输入复制到每个指定文件,并显示到标准输出。相较于 cat >,tee 后面可以直接跟文件名,不需要重定向直接输出。当需要追加内容时,需要使用-a选项。

[root@localhost opt]# tee file.txt << eof
> 1
> 2
> eof
1
2
[root@localhost opt]# cat file.txt 
1
2

2. expect

2.1 定义与格式

是建立在tcl(tool command language)语言基础上的一个工具,它不同于 bash,常被用于进行自动化控制和测试,解决 shell 脚本中交互的相关问题。工具需要安装。

格式:

expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]

2.2 expect基本命令

① 脚本解释器:expect 脚本中首先引入文件,表明使用的是哪一种shell。expect的为:/usr/bin/expect

② spawn命令:用于捕捉关键词,后面常跟一个linux执行命令

③ expect命令:用于判断上层捕捉输出的结果是否有指定字符,有则立即返回,没有则默认等待10s

④ exp_continue命令:expect多分支判断时使用

⑤ send命令:expect命令判断完成需要返回时,发送需要交互的指令,想要传递给电脑的文字或字符,该命令不能自动回车换行,\n和\r是回车

⑥ set命令:可用于设置变量、设置expect超时时间,默认是10s,例set time out 30

⑦ set设置位置变量:set password [lindex $argv 0] ,设置时从0开始,执行脚本时在脚本后跟参数即可

⑧ 结束符:(1) expect eof 结束并返回原来环境,原来主机

               (2) interact 结束但是不会返回原来的地方,保持当前状态,当前主机

示例:

[root@localhost opt]# expect
expect1.1> expect "fql" {send "hi"}
fql
hiexpect1.2>
# > expect捕捉屏幕上的输出,只要出现“hi”,发送后面的语句

应用:免交互传输文件,远程拷贝

[root@localhost opt]# vim test
#!/usr/bin/expect
spawn scp /etc/passwd 192.168.190.101:/opt
#监控scp命令,出现scp命令开始捕捉屏幕内容
expect {
        "yes/no" {send "yes\n";exp_continue}
        "password" {send "123123\n";}
}
#捕捉屏幕上的关键字,出现yes/no,输入yes。exp_continue代表继续捕捉password,出现password 输入密码;\n\r回车
expect eof
#代表结束

[root@localhost ~]# expect test
spawn scp /etc/passwd 192.168.190.101:/opt
The authenticity of host '192.168.190.101 (192.168.190.101)' can't be established.
ECDSA key fingerprint is SHA256:aIqKteFz37bh8tOF7A07YElsVqfHgBSbxwkKXK9dfks.
ECDSA key fingerprint is MD5:9c:5a:7f:ec:d9:0c:2a:b2:9d:9e:03:77:f3:87:36:d4.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.190.101' (ECDSA) to the list of known hosts.
[email protected]'s password: 
passwd                                                          100% 2101   722.5KB/s   00:00 

192.168.190.101
[root@localhost opt]# ll
总用量 4
-rw-r--r--. 1 root root 2101 1月  31 16:36 passwd

2.3 interact与expect eof区别演示(免交互ssh主机

#!/usr/bin/expect
spawn ssh 192.168.190.101
expect {
        "yes/no" {send "yes\n";exp_continue}
        "password" {send "123123\n";}
}
expect eof
#interact

[root@localhost ~]# expect test1
spawn ssh 192.168.190.101
The authenticity of host '192.168.190.101 (192.168.190.101)' can't be established.
ECDSA key fingerprint is SHA256:aIqKteFz37bh8tOF7A07YElsVqfHgBSbxwkKXK9dfks.
ECDSA key fingerprint is MD5:9c:5a:7f:ec:d9:0c:2a:b2:9d:9e:03:77:f3:87:36:d4.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.190.101' (ECDSA) to the list of known hosts.
[email protected]'s password: 
Last login: Wed Jan 31 16:37:35 2024 from 192.168.190.1
[root@localhost ~]# [root@localhost ~]#                 
#默认10秒钟返回
如果配置改为interact,则不会返回

2.4 批量远程新建用户

[root@localhost opt]# vim passwd
#!/bin/bash
ip="192.168.190"
hostlist="
101
102
"
pass=123123

for i  in $hostlist
do
/usr/bin/expect << EOF
spawn ssh ${ip}.${i}
expect {
        "yes/no"    {send "yes\r";exp_continue}
        "password"  {send "$pass\r"}
}
expect "*]#" { send "useradd test\n" }
expect "*]#" { send "echo 123123 | passwd --stdin test\r" }
expect "*]#" { send "exit\r" }

expect eof
EOF
done
[root@localhost opt]# bash passwd

192.168.190.101:
[root@localhost ~]# id test
uid=1001(test) gid=1001(test) 组=1001(test)
192.168.190.102:
[root@localhost ~]# id test
uid=1001(test) gid=1001(test) 组=1001(test)

二、字符处理

1. 字符串切片

1.1 基于偏移量取字符

取字符串的长度

${#var}:返回字符串变量var的字符的长度,一个汉字算一个字符

[root@localhost opt]# str=`echo {a..z} | tr -d " "`
[root@localhost opt]# echo ${#str}             #str变量里一共有26个字符
26
[root@localhost opt]# str=123你好
[root@localhost opt]# echo ${#str}
5

跳过左边的字符

${var:offset}
#返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到 ${#var}-1 之间(bash4.2后,允许为负值)
${var:offset:number}
#返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分

[root@localhost opt]# echo ${str}
abcdefghijklmnopqrstuvwxyz
[root@localhost opt]# echo ${str:2:3}     #跳过前两个往后取三个
cde
[root@localhost opt]# echo ${str: -2}     #取后两个
yz

掐头去尾

${var:offset:-length}
#从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容,即:掐头去尾

[root@localhost opt]# echo ${str:3:-3}    #去掉前后三个,取中间
defghijklmnopqrstuvw

取倒数的范围

${var: -length:-offset}
#先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容,注意:-length前空格,并且length必须大于offset

[root@localhost opt]# echo ${str: -5:-3}
vw                                         #倒数5个到,倒数3个

1.2 基于模式取子串

删左留右

${var#*word}
#其中word可以是指定的任意字符,自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符串(含)之间的所有字符,即懒惰模式,以第一个word为界删左留右

#同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容,即贪婪模
式,以最后一个word为界删左留右
${var##*word}

[root@localhost ~]# url="http://www.baidu.com/index.html"
[root@localhost ~]# echo ${url#*/}
/www.baidu.com/index.html
#慵懒模式。从左边开始匹配,遇到/就把/左边的都删除包括/本身
[root@localhost ~]# echo ${url##*/}  
index.html  
#贪婪模式。一直匹配到最后一个/

删右留左

${var%word*}
#其中word可以是指定的任意字符,功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符串(含)之间的所有字符,即懒惰模式,以从右向左的第一个word为界删右留左
${var%%word*}
#同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符,即贪婪模式,以从右向左的最后一个word为界删右留左

[root@localhost ~]# url="http://www.baidu.com:8080/index.html"
[root@localhost ~]# echo ${url%:*}
http://www.baidu.com
[root@localhost ~]# echo ${url%%:*}
http

2. 查找替换

${var/pattern/substr}
${变量/搜索的字符串/修改的字符串}
#查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之

[root@localhost ~]# user=`grep fql /etc/passwd`
[root@localhost ~]# echo ${user}
fql:x:1000:1000:fql:/home/fql:/bin/bash
[root@localhost ~]# echo ${user/fql/aaa}
aaa:x:1000:1000:fql:/home/fql:/bin/bash

${var//pattern/substr}
#查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之

[root@localhost ~]# echo ${user//fql/aaa}
aaa:x:1000:1000:aaa:/home/aaa:/bin/bash

${var/#pattern/substr}
#查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
在此处#代表开头,不支持贪婪模式

[root@localhost ~]# echo ${user/#fql/aaa}
aaa:x:1000:1000:fql:/home/fql:/bin/bash

${var/%pattern/substr}
#查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
在此处 % 代表结尾,不支持贪婪模式

[root@localhost ~]# echo ${user/%bash/nologin}
fql:x:1000:1000:fql:/home/fql:/bin/nologin

3. 查找删除

${var/pattern}
#删除var表示的字符串中第一次被pattern匹配到的字符串

[root@localhost ~]# user=`grep fql /etc/passwd`
[root@localhost ~]# echo ${user/fql}
:x:1000:1000:fql:/home/fql:/bin/bash

${var//pattern}
删除var表示的字符串中所有被pattern匹配到的字符串

[root@localhost ~]# echo ${user//fql}
:x:1000:1000::/home/:/bin/bash

${var/#pattern}
删除var表示的字符串中所有以pattern为行首匹配到的字符串

[root@localhost ~]# echo ${user/#fql}
:x:1000:1000:fql:/home/fql:/bin/bash

${var/%pattern}
删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串

[root@localhost ~]# echo ${user/%bash}
fql:x:1000:1000:fql:/home/fql:/bin/

4. 大小写转换

${var^^}:把var中的所有小写字母转换为大写
${var,,}:把var中的所有大写字母转换为小写

[root@localhost ~]# a=aBc
[root@localhost ~]# echo ${a^^}
ABC
[root@localhost ~]# echo ${a,,}
abc

本文转载自: https://blog.csdn.net/qq_64612585/article/details/135952067
版权归原作者 Fang_Qianling 所有, 如有侵权,请联系我们删除。

“Expect交互工具与字符处理”的评论:

还没有评论