【expect处理交互数据】
spawn ssh root@192.168.122.214 # 启动ssh远程IP
expect "#"
send "useradd yangyang\r"
send "pwd\r"
send "exit\r"
expect eof
/usr/bin/expect <<-EOF
set timeout 10
spawn ssh-copy-id $ip
expect {
"yes/no" { send "yes\r"; ex_continue }
"password:" { sed "$password\r" }
}
expect eof
EOF
set ip [lindex $sargv 0] 第一个位置变量相等于$1
set user [lindex $argv 1] 第二个位置变量相等于$2
【shell数组】
普通数组:只能使用整数作为整数索引
关联数组:可以使用字符串作为数组索引
索引(下标)
declare -A info # 声明关联数组
declare -a # 查看数组
访问数组元数:
echo ${array1[0]} 访问数组中的第一个元素
echo ${array1[@]} 访问数组中所有元素
echo ${#array1[@]} 统计数组元数的个数
echo ${!books[@]} 获得数组的索引
echo ${array1[@]:1} 从数组下标1开始
echo ${array1[@]:1:2} 从数组下标开始,访问两个元素
【实施】
统计
sort # 按排序忽略重复输出
-d: 只显示重复的行
uniq # 忽略重复行输出
-u:去掉了连续的重复行.如果只想保留文件中的唯一
-c:去重复,并计算每行出现的次数
!!!把要统计的对象作为数组的索引 ;索引对应的值
watch # 查看实施的状态
clear # 清屏
【函数】
传参 $1,$2
变量 local
返回值 return $?
=================================================================
在shell中定义函数可以使用代码模块化,便于复用代码
函数必须先定义才可以使用
[定义函数]
方法一:
函数名(){
函数要实现的功能代码
}
方法二:
function(){
函数要实现的功能代码
}
[调用函数]
函数名
阶乘:(实例)
5的阶乘:5*4*3*2*1
4的阶乘:4*3*2*1
【函数的输入】
函数的返回值,是最后一条命令执行的结果
let # 数值计算
return # 自定义函数的返回值,但不能超过255的值
result=函数名
用一个变量接受函数的输出就可以输出大于255的值
【函数传参】
程序参数:程序和(脚本)执行时,程序和(脚本)下的参数
函数参数:调用函数,在函数后面加的位置参数
[数组变量]
在函数内部的变量,是不会影响shell中的变量
# 函数接受位置参数 $1 $2 $3 ...$n
# 函数接受数组变量 $*或$@
# 函数没将收到的所有参数赋值给数组 newarray=($*)
【shell内置命令】
:
break # 结束当前循环,或跳出本层循环
continue # 忽略本次循环剩余的代码,直接进入下一次循环
true
false
shift # 使位置参数向左移动,默认移动一位,可是使用shift2
exit # 退出整个程序
【正则表达式RE】
文本处理工具:vim、sed、awk、grep
一、什么是正则表达式?
正则表达式是一种字符模式,用于查找过程中匹配制定的字符。
匹配数字: ^[0-90]+$
匹配Mail: [a-z0-9_]+@[a-z0-9]+\.[a-z]+
匹配IP: [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
或
[[:digit:]]{1,3}\. [[:digit:]]{1,3}\. [[:digit:]]{1,3}\. [[:digit:]]{1,3}
【元字符】
定义:元字符是这样一类字符,他们表达的是不同于字面本身的含义
shell元字符(也称为通配符) # 由shell来解释
正则表达式元字符 # 有各种执行模式匹配操作的程序来解析
vim的元字符
实例:
%s/\<[Tt]om\>/David/g
====基本正则表达式元字符============
^ 行首定位符
$ 行尾定位符号
. 匹配单个字符
* 匹配前导符0到多次
.* 任意多个字符
[] 匹配指定范围内的一个字符
[ - ] 匹配指定范围内的一个字符
[ ^ ] 匹配不在指定组内的字符
\ 用来转义元字符
< 词首定位符
> 词尾定位符
(…) 匹配稍后使用的字符的标签
x\{m\} 字符x重复出现m次
x\{m,\} 字符x重复出现m次以上
x\{m,n\} 字符x重复出现m到n次
====扩展正则表达式元字符============
+ 匹配一个或多个前导字符
? 匹配0个或一个前道字符
a|b 匹配a或b
() 组字符
(…)(…)\1\2 标签匹配字符
x{m} 字符x重复m次
x{m,} 字符x重复至少m次
x{m,n} 字符x重复m到n次
实例:
love*
love?
love+
love{2}
lo(ve)*
lo(ve)?
lo(ve)+
lo(ve){2}
共同的特性:* ? + {} 都不是给自己活者的,都是为别人而活
凡是见到:* ? + {} 都要往前看,前面没有()看一个字符,前面有()看整个括号
====POSIX字符类=========================
表达式 功能
[:alnum:] 字母与数字字符
[:alpha:] 字母字符(包括大小写字母)
[:blank:] 空格与制表符
[:digit:] 数字字母
[:lower:] 小写字母
[:upper:] 大写字母
[:punct:] 标点符号
[:space:] 包括换行符,回车等在内所有空白
【文本处理:grep】
grep: 在文件中全局查找指定的正则表达式,并打印所有包含该表达式的行
egrep: 扩展的egrep,支持更多的正则表达式元字符
fgrep: 固定grep(fixed grep),有时也被称作快速(dasr grep),它按字面解释所有的字符
grep命名格式
grep [选项]... PATTERN [FILE]...
-q :安静模式
找到: grep返回的退出状态为0
没找到: grep返回的退出状态为1
找不到指定文件: grep返回的退出状态为2
grep使用的元字符
grep: 使用基本元字符集: ^ $ . * [] [^] \<\> \(\) \{\} \+ \|
egrep(或grep -E): 使用扩展元字符集: ? + {} | ()
!!!grep也可以使用扩展集中的元字符,仅需要对这些元字符前置一个反斜线
\w 所有字母和数字,称为字符[a-zA-Z0-9] 'l[a-zA-Z0-9]*ve' 'l\w*ve'
\W 所有字母与数字之外的字符,称为非字符 'love[^a-zA-Z0-9]+' 'love\W+'
\b 词边界 '\<love\>' '\blove\b'
grep选项
-i 忽略大小写
-l 只列出匹配行所在的文件名
-n 在每一行前面加上它在文件中的相对行号
-c 显示成功匹配的行数
-s 禁止显示文件不存在或文件不可读的错误信息
-q 静默--quiet,--slient
-v 返乡查找,只显示不匹配的行
-R 递归针对目录
--color 颜色
-o 只显示匹配的内容
-A 查看后两行
-B 查看中间两行
-C 查看前两行
【文本处理sed】
sed是一种在线的、费交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed
命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,知道文件末尾。文件内容并没有改变,
除非你使用重定向储存输出。Sed主要用来自动编辑一个或多个文件;简化对文件的返回操作;编写转换程序等。
命令格式
sed [options] 'command' file(s)
sed [options] -f scriptfile (s)
支持正则表达式
sed在文件中查找模式时也可以使用正则表达式(RE)和各种元字符。正则表达式视阔在斜杠间的模式,用于查找和替换
使用基本元字符集:^ $ . * [] [^] \<\> \(\) \{\}
使用扩展元字符集:? + {} | ()
使用扩建元字符的方式:
\+
swd -r
sed扩展
===地址(定址)
地址用于决定对哪些行进行编译。地址形式可以是数字、正则表达式或二者的结合、如果没有指定地址,sed将处理输入文件中的所有行
sed -r 'd' /etc/passwd
sed -r '3d' /etc/passwd
sed -r '1,3' /etc/passwd
sed -r '/root/,5d' /etc/passwd
sed -r 's/root/alice/g' /etc/passwd
sed -r '/^adm/,20d' /etc/passwd 删除到20行
sed -r '/^adm/,+20d' /etc/passwd 再删除20行
sed -r '2,5d' /etc/passwd
sed -r '/root/d' /etc/passwd
sed -r '/root/!d' /etc/passwd
sed -r '1~2d' /etc/passwd 删除所有奇数行
sed -r '0~2d' /etc/passwd 删除所有偶数行
sed命令
告诉sed对指定进行何种操作,包括打印、删除、修改等。
命令 功能
a 在当前行后添加一行或多行
c 用新文本修改(替换)当前行中的文本
d 删除行
i 在当前行之前插入文本
l 列出非打印字符
p 打印行
n 读入下一输入行,并从下一条命令而不是第一条命令开始对其的处理
q 结束或退出
! 对所选行以外的所有行应用命令
S 用一个字符串替换另一个
s 全局替换
g 全局替换
i 忽略大小写
r 从文件中读
w 将行写入文件
y 将字符转换为另一字符(不支持正则表达式)
h 把模式空间里的内容追加到暂缓冲区(覆盖)
H 把模式空间里的内容追加到暂存缓冲区
g 取出暂存缓冲区的内容,将其复制到模式空间,覆盖该处原有内容
G 取出暂存缓冲区的内容,将其复制到模式空间,追加在原有内容后面
x 交换暂存缓冲区与模式空间的内容
===选项
-e 允许多项编辑
-f 指定sed脚本文件名
-n 取消默认的输出
-i inplace,就地编辑
-r 支持扩展元字符
【文本处理awk】
[awk简介]
awk是一种变成语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。
awk的处理文本和数据的方式是这样,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所制定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weiberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。
[awk的两种形式语法格式]
awk [options]'commands' filenames
awk [options] -f awk-script-file filenames
====options:
-F 定义输入字段分隔符,默认的分隔符是空格或制表符(tab)
====command:
BEGIN{} {} END{}
行处理前 行处理 行处理后
awk工作原理
(1)awk使用一行作为输出,并将这一行赋给内部变量$0,没一行也可以称为一个记录,以换行符结束。
(2)行被:(默认为空格或制表符)分解成字段(或域),每个字段储存在已编号的变量中,从$1开始,最多达100个字段。
(3)awk如何知道用空格来分隔字段的呢?因为有一个内部变量FS来确定字符分隔符。初始时,FS赋为空格
(4)awk打印字段时,将以设置的方法使用print函数打印,awk在打印字段间加上空格,因为$1,$3之间有一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格
(5)awk输出之后,将从文件中获取另一行,并将其储存在$0中,覆盖原来的内容,然后将新的字符串分割成字段并进行处理。该过程将持续到所有行处理完毕
====记录与字段相关内部变量;man awk
$0: awk变量$0保存当前记录的内容
NR: 到目前为止看到的输入记录的总数。
FNR: 当前输入文件中的输入记录编号。
NF: 保存记录的字段数
FS: 输入字段分隔符,默认空格
OFS: 输出字段分隔符
RS: 输入记录分隔符,默认为换行
ORS: 输出记录分隔符,默认为换行。
区别:
字段分隔符:FS OFS 默认空格或制表符
记录分隔符:RS ORS 默认换行符
====格式化输出
%s 字符类型
%d 数值类型
%f 浮点类型
- 表示左对齐,默认是右对齐
print默认是不会在行尾自动换行,加\n
====awk模式和动作
任何awk语句都有模式和动作组成。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分。动作将时刻保持执行状态。模式可以是任何条件语句或正则表达式。模式包括两个特殊字段BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态。
====正则表达式
匹配记录(整行)
awk ‘/^alice/’ /etc/passwd
awk ‘$0~/alice/’ /etc/passwd
awk ‘!~/alice/’ /etc/passwd
awk ‘$0 !~/alice/’ /etc/passwd
匹配字段:匹配操作符(~ !~)
awk -F: '$1~ /^alice/' /etc/passwd
awk -f: '$NF !~/bash/' /etc/passwd
=====比较表达式:
比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关旭运算符,用于比较数学与字符串。
关系运算符号
< 小于
<= 小于或等于
== 等于
!= 不等于
>= 大于等于
> 大于
====条件表达式
awk -F: ‘{if($3>300){print $3}else{print $3}}’ /etc/passwd
====算数运算:+ - * / % ^
可以在模式中执行计算,awk都将按浮点数方式算数运算
awk -F: '$3 * 10 > 500' /etc/passwd
awk -F: '{ if($3*10>500){print $0} }' /etc/passwd
====逻辑操作符和复合模式
&& 逻辑与
|| 逻辑或
! 逻辑非
awk -F: '$1~/root/ && $3<=15' /etc/passwd ~:表示匹配
awk -F: '$1~/root/ || $3<=15' /etc/passwd
awk -F: '!($1~/root/ || $3<=15)' /etc/passwd
====模式范围
awk '/Tom/,/Souzanne/' filename
====awk脚本编程
if语句
格式: {if(表达式){语句;语句...}}
awk -F: ‘{if($3==0){print $1 “is adminstrator.”}}’ /etc/passwd
awk -F: '{if($3>0 && $3<100){i++;}}'END{print i} /etc/passwd
if..else语句
格式: {if(表达式){语句;语句;...}else{语句;语句;...}}
awk -F: '{if($3==0){print $1}else{print $7}}' /etc/passwd
awk -F: '{if($3==0){count++}else{i++}}' /etc/passwd
awk -F: '{if($3==0){count++}else{i++}}END{"管理员个数:"count;print"系统用户数:"i}' /etc/passwd
if...else if...else语句:
格式: {if(表达式1){语句;语句;...} else if(表达式2){语句;语句;...} else if(表达式3) {语句;语句;...}else{语句;语句;...}}
awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i;print k;print j}' /etc/passwd
awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理员个数:"i; print "普通用个数:"k; print "系统用户:"j}'/etc/passwd
====while循环
awk ‘BEGIN{i=1;while(i<=10){print i; i++}}’
awk -F: ‘/^root/{i=1; while(i<=7){print $i;i++}}’ passwd
awk -F: ‘{i=1;while(i<=NF){print $i; i++}}’ /etc/hosts
awk -F: ‘{i=1;while(i<=10){print $0; i++}}’ /etc/passwd
====for循环
awk ‘BEGIN{for(i=1;i<=5;i++){print i}}’
awk -F: ‘{for(i=1;i<=10;i++){print $0}}’ /etc/passwd
awk -F: ‘{for(i=1;i<=NF;i++){print $i}}’ passwd
=====数组
awk -F: ‘{username[i++]=KaTeX parse error: Expected 'EOF', got '}' at position 2: i}̲ END{print user…i} END{print username[1]}’ /etc/passwd i++从0开始
awk -F: ‘{username[i++]=$i} END{print username[0]}’ /etc/passwd
=====索引遍历
awk -F: ‘{username[x++]=$1} END{for(i in useranme){print i,username[i]}}’ /etc/passwd
awk -F: ‘{username[++x]=$1} END{for(i in username){print i,usernaem[i]}}’ /etc/passwd
awk -F: '{root[$NF]++} END{for(i in root){print i,root[i]}}' /etc/passwd # 统计/etc/passwd中各种类型shell数量
netstat -ant |grep ':80' | awk '{status[$NF]++} END{for(i in status){print i,status[i]}}' # netstat方式网站访问统计状态
netstat -ant |grep ':80' | awk '{status[$NF]++} END{for(i in status){print i,status[i]}}'| sort -k2 -n | head netstat方式网站访问统计状态,并排序
ss -an |grep ':80' |awk '{status[$2]++} END{for(i in status){print i,status[i]}}' # ss方式网站访问统计状态
!!!思路:将需要统计的内容(某一个字段)作为数组的索引++
====awk函数
awk -F: ‘
1
/
.
.
.
.
1~/^....
1 /..../{count++; print $1} END{print "count is: " count}’ /etc/passwd
====awk外部变量
(在双引号的情况下使用)
var=“bash”
echo “unix script” |awk “gsub(/unix/,”$var")"
(在单引号的情况下使用)
var=“bash”
echo “unix script” | awk ‘gsub(/unix/,"’"$var"’")’
df -h |awk '{ if(int($5)>5){print $6":"$5} }'
或者
i=5
df -h |awk '{if(int($5)>'''$i'''){print $6":"$5} }'
(awk参数-v(建议))
var=“bash”
echo “unix script” | awk -v var=“bash” ‘gsub(/unix/,var)’