[root@room9pc01 ~]# seq 5
1
2
3
4
5
[root@room9pc01 ~]# seq 2 5
2
3
4
5
seq 1 2 10
1
3
5
7
9
[root@desktop0 ~]# seq 10 -2 1
10
8
6
4
2
/etc/profile #定义的系统变量文件
回车:
\n或\r
num=$[RANDOM%100+1]
#0-100随机数
>
>> 2> 2>> &> &>>
echo
' '实现输出换行
echo
'ff
>
fffff
>
ff'
ff
fffff
ff
\
可使命令在下一行继续写
[root@desktop0
~]# echo d\
>
d\
>
dd
[root@svr5
~]#
test=11
[root@svr5
~]#
echo ${test}RMB
//区分后可以识别
11RMB
[root@svr5
~]#
unset test //撤销变量test
a="ab
d"
a='$abc'
单引号可以屏蔽特殊符号的功能
`
` 等同
$(
)
将回显功能关闭(stty
-echo),开启后用户在屏幕上输出是看不到的
*将回显功能恢复(stty
echo)。
使用export发布全局变量
默认情况下,自定义的变量为局部变量,只在当前Shell环境中有效,而在子Shell环境中无法直接使用。比如已定义的SCHOOL变量,当进入到sh或bash子Shell后,变量SCHOOL将处于未定义的状态:
[root@svr5
~]#
export
yy //发布已定义的变量
[root@svr5
~]#
export
XX="1234"//发布新变量
env可查看所有环境变量:
set可查看所有变量(包括env能看到的环境变量):
全局文件为/etc/profile,对所有用户有效;用户文件为~/.bash_profile,仅对指定的用户有效。
PS1表示Shell环境的一级提示符,即命令行提示符(\u
用户名、\h
主机名、\W
工作目录、\$
权限标识):
PS2表示二级提示符,出现在强制换行、at任务编辑等场合:
[root@svr5
~]#
vim location.sh
!/bin/bash
echo
$0//脚本的名称
如果用 .
或者
source
当前shell执行
显示 shell名称
echo
$1//第一个参数
echo
$2//第二个参数
echo
$*//所有参数
echo
$# //用户
输入的参数总个数
echo
$$ //当前进程的进程号
echo
$?//上一个程序的返回状态码
[root@svr5
~]#
chmod +x
location.sh
//添加可执行权限
整数运算工具
expr
$[9+9] let
[root@svr5
~]#
X=1234//定义变量X[root@svr5
~]#
expr $X +78//加法1312
[root@svr5
~]#
expr $X -78//减法1156
[root@svr5
~]#
expr $X \*78//乘法,操作符应添加\转义96252
[root@svr5
~]#
expr $X /78//除法,仅保留整除结果15
[root@svr5
~]#
expr $X %78//求模64
let
X;
echo $X # X(X=X+78)
x=$[5*6]
echo
$]
echo
$[RANDOM%10] #0~9之间的随机数
echo
"scale=3;10/3" | bc
#指定小数位数
echo
"1+1" | bc
------------------------------------------let
可以进行赋值运算let
x=x+1或者let
x+=1或者let
x++
-------------------------------------------x=$[x+2]
字符
==
!=
-z #-z判断是否为空
数字
-eq
-ne -ge -gt -le -lt
文件
-e
-f -d -r -w -x
[-e
"/etc/fstab"]&&
echo "存在"||
echo "不存在"
[-r
"/tmp/test.txt"]&&
echo "可读"||
echo "不可读"
#是否可读是对当前用户来说的
#权限判断是对当前用户来说的
逻辑与
&&
逻辑或
||
逻辑判断也遵循匹配即停止
[root@desktop0
~]# echo {1..3} #不支持变量{1..$x}
错误
1
2 3
[root@desktop0
~]# seq 3
1
2
3
[root@desktop0
~]# x=3
[root@desktop0
~]# seq $x
#支持变量
1
2
3
[root@server0
opt]# seq 6 9
6
7
8
9
!/bin/bash
for
i in `seq $1` #seq
是命令
所以需要``括起来
do
echo
第${i}次
#{}是一种格式
代表括号内的一段数字 不需要 `
`
done
[root@svr5
~]# vim test.sh
#!/bin/bash
case
$1 in
redhat|xiaoming|lisi)
# |
满足其中一个即可
echo
"fedora";;
fedora)
echo
"redhat";;
*)
//默认输出脚本用法
echo
"用法:
$0 {redhat|fedora}"
esac
A
&& B //仅当A命令执行成功,才执行B命令
A||B
//仅当A命令执行失败,才执行B命令
A;
B //执行A命令后执行B命令,两者没有逻辑关系
A&&
B || C //先运算A&&
B 都成立就不会执行C
否则就执行C
[root@svr5
~]#
var1="nb";
var2=""
[root@svr5
~]#
[-z
"$var1"]&&
echo "空值"||
echo "非空值"
# -z判断是否是空值
非空值
#-n非空值为真
[root@svr5
~]#
[-z
$var2 ]&&
echo "空值"||
echo "非空值"
空值
//变量var2已设置,但无任何值,视为空
[root@svr5
~]#
[!-z
$var1 ]//测试var1是否为非空
vim
cd
!/bin/bash
cd
/opt
[root@desktop0
~]# bash
/root/cd #开启新进程
执行之后 退出
[root@desktop0
~]#
. /root/cd
#不开启新进程
[root@desktop0
opt]#
!/bin/bash
mycd(){
echo
$1
}
mycd
lisi
echo
$1
[root@desktop0
~]# . /root/cd zhangsan
#两个$1的区别
lisi
zhangsan
扩展的echo使用\033[固定格式,34m是颜色
0m是屏幕后面的输出恢复默认颜色
echo
-e "\033[34m里斯\033[0m"
[root@room9pc01
~]# i=0
[root@room9pc01
~]# let i++ && echo $i
[root@room9pc01
~]# i=0
[root@room9pc01
~]# let i++ || echo $i # let 变量初始值是0时,let
i++ 退出时状态时非0
1
[root@room9pc01
~]# let g++
[root@room9pc01
~]# echo $?
1
[root@room9pc01
~]# echo $g
1
if
[ $JF -ge 90 ]
; then
echo
"$JF 分,神功绝世"
elif
[
$JF -ge 60 ]
; then
echo
"$JF 分,略有小成"
else
echo
"$JF 分,初学乍练"
fi
for
i in {1..100} 或者
`seq
100` 或者
`cat
/opt/user.txt` #可以是数字和文本
do
循环内容
done
while
[ 判断
]
#拓展
while
:
无限循环
do
循环内容
let
i++
#可通过改变判断条件的值
实现有限循环
done
case
变量
in
模式1)
执行指令;;
模式2)
执行指令;;
*)
//默认输出脚本用法
执行命令;;
esac
函数名(){
命令序列
....
}
function函数名
{
命令序列
....
}
Shell版本的fork炸弹
.(){
.|.&
}
.
截取字符串
空格也算一个字符 a="ab
cd e"
echo
${#a} #字符长度
7
${变量名:起始位置:长度}
expr
substr "$变量名"
起始位置
长度
echo
$变量名
|
cut -b 起始位置-结束位置
[root@desktop0
~]# a=abcdef
[root@desktop0
~]# echo ${a:1:3}
从序号1开始位
位置从0开始
bcd
[root@desktop0
~]# echo ${a:0:3}
从序号0开始位
abc
[root@desktop0
~]# echo ${a::3}
0可以省略
abc
[root@desktop0
~]# echo $a | cut
-b 1 截第1位
位置 从1开始
a
[root@desktop0
~]# echo $a | cut
-b 2-3 截第2位
位
bc
# -3 截开头到第三
3-
第三到结尾
[root@desktop0
~]# expr
substr $a 2 3 从序号2开始位
位置从1开始
bcd
[root@desktop0
~]# expr substr $a 1
expr:
语法错误
[root@desktop0
~]# expr substr $a 1 1
a
[root@desktop0
~]# echo ${a:1:1}
b
字符串拼接[root@server0
~]# a=q #数字也可以拼接
正常纯数字 还可以计算
[root@server0
~]# b=w
[root@server0
~]# c=$c$a$b
[root@server0
~]# echo $c
qw
字符串查找并替换
只替换第一个匹配结果:${变量名/old/new}
替换全部匹配结果:${变量名//old/new}
[root@server0
~]# a=`cat /etc/passwd | head -1`
[root@server0
~]# echo $a
root:x:0:0:root:/root:/bin/bash
[root@server0
~]# b=${a/root/jjjj};echo
$b 一个/
只替换第一个目标字符串
jjjj:x:0:0:root:/root:/bin/bash
[root@server0
~]# b=${a//root/jjjj};echo
$b 两个/替换全部目标字符串
jjjj:x:0:0:jjjj:/jjjj:/bin/bash
[root@server0
~]# b=${a//root/};echo $b
:x:0:0::/:/bin/bash
字符串查找并删除
a=root:x:0:0:root:/root:/bin/bash
从左开始查找:掐头
从开头匹配
${a#root}
找到第一个目标即停止,从开头匹配如果左起第一个不是root,代表没有匹配项
${a##oot}
从开头匹配(开头匹配不上即停止),删掉一层,继续匹配,找到所有目标(像扒皮一样删除)
${a#*t}
*是通配符,找到第一个*t
,即停止
${a##*t}
一直找到最后一个*t
,把头全删掉
从右开始查找:去尾
${a%root}
从右开始查找,%只删除一层
${a%%root}
%%扒皮查找
${a%root*}
${a%%root*}
a=root:x:0:0:root:/root:/bin/bash
[root@server0
~]# echo ${a#ro}
ot:x:0:0:root:/root:/bin/bash
[root@server0
~]# echo ${a#oo}
root:x:0:0:root:/root:/bin/bash
备用值
x=f
x=${x:-123}
#当x已经被赋值时,备用不会生效{备用值
[root@server0
opt]# echo $x
f
计算1到n的求和,如果用户无输入时,则n为1
!/bin/bash
read
-p "qiuhe:" p
p=${p:-1}
# 备用值
for
i in `seq $p`
do
let
x+=i
done
echo
$x
基本正则列表
正则符号 |
描述 |
^ |
匹配行首 |
$ |
匹配行尾 |
[ |
集合,匹配集合中的任意单个字符 |
[^] |
对集合中单个字符取反 |
. |
匹配任意单个字符(代表一个字符) |
* |
匹配前一个字符任意次数 |
\{n,m\} |
匹配前一个字符n到m次 |
\{n\} |
匹配前一个字符n次 |
\{n,\} |
匹配前一个字符n次以上 |
\(\) |
保留 |
扩展正则表达式
正则符号 |
描述 |
+ |
前一个字符最少匹配一次 |
? |
前一个字符最多匹配一次 |
{n,m} |
前一个字符匹配n到m次 |
( |
组合为整体。保留(代表一个字符 |
| |
或者 |
\b |
单词边界(\broot\b,代表匹配root两边是空) |
[root@svr5
~]#
grep HISTSIZE /etc/profile
HISTSIZE=1000
*清空历史的命令。
[root@svr5
~]#
history -c
//清空自己的历史命令
[root@svr5
~]#
>~/.bash_history
//清空记录文件
sed
支持管道
正则条件要放在//内
条件可以是行号或者/正则/
没有条件时,默认为所有条件
指令可以是增、删、改、查等指令
默认sed会将所有输出的内容都打印出来,可以使用-n屏蔽默认输出
选项中可以使用-r选项,让sed支持扩展正则
-n(屏蔽默认输出,默认sed会输出读取文档的全部内容)
-r(让sed支持扩展正则)
-i(sed直接修改源文件,默认sed只是通过内存临时修改文件,源文件无影响)
指令:
p
d s i a c r w
sed
[-选项]
'/定位筛选条件/指令
'
文件
#选项可省略,定位筛选条件支持正则(定位到那一行)
sed
'' abc.txt #会默认输出文件内容
逐行显示
sed
-n '' abc.txt #-n 取消默认输出
sed
-n 'p' abc.txt #命令p(print)输出全部,逐行显示
sed
-n '3p' abc.txt #输出第三行
sed
-n '1,2p abc.txt #输出第1到第2行
sed
-n '1,+2p' abc.txt #输出第1行
加后面两行
sed
-n '1p;3p' abc.txt #第一和第三行,
;
隔开命令
sed
-n '/root/p' /etc/passwd #输出筛选结果
格式:/筛选条件
/
支持正则筛选
sed
-n '1~2p' abc.txt #输出第一行
~连续跳步
继续输出跳步所在的行(实现只输出奇数行)
sed
-n '$='
a.txt //输出文件的行数
sed
'/991/d' abc.txt #d删除
用法同p
sed
'/xml/d'
a.txt
//删除所有包含xml的行
sed
'/xml/!d' a.txt //删除不包含xml的行,!符号表示取反
sed
'$d' a.txt //删除文件的最后一行
sed
'/^$/d' a.txt //删除所有空行(没有空格的行)
sed
''
abc.txt #s替换
#
:只处理第二行,没有时
逐行处理
:每一行的第3个old,没有参数时,只替换第一个old
sed
's/old/new/g'
abc.txt
#
g每一行的所有old
sed
-n 's/2017/xxxx/p' test.txt
#p只输出定位处理的那一行
替换操作的分隔“/”可改用其他字符,如#、&等,便于修改文件路径
sed
's#/bin/bash#/sbin/sh#'
a.txt
//将/bin/bash替换为/sbin/sh
sed
's/\/bin\/bash/\/sbin\/sh/' b.txt
sed
'4,7s/^/#/'
a.txt
//将第4~7行注释掉(行首加#号)
sed
's/^#an/an/'
a.txt
//解除以#an开头的行的注释(去除行首的#号)
sed
'/kk/s/123/***/' shiyan #将匹配kk的那行进行替换
123
123
123
123
kkk***
[root@svr5
~]#
sed -r
's/^(.)(.*)(.)$/\3\2\1/'
nssw.txt
#将文件中每行的第一个、倒数第1个字符互换
sed
-r
's/([A-Z])/[\1]/g'
nssw.txt
#为文件中每个大写字母添加括号
[root@server0
~]# sed -n '/^root/,+2p'
/etc/passwd #综合使用
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@server0
~]# cat aaa
1
2
3
4
[root@server0
~]# sed -r "1h;2g" aaa #数字是指定行,没有数字
代表所有行
1
1
3
4
[root@server0
~]# sed -r "1H;2G" aaa #粘贴板中默认有一空行
1
2
1
3
4
h,H复制制定行行到粘贴板,h是覆盖到粘贴板,H是追加的到粘贴板,g是将指定行覆盖粘贴,G是在指定行追加粘贴。粘贴板是内存不是硬盘
$
cat foo
11111111111111
22222222222222
33333333333333
$
sed '1!G;h;$!d' foo
33333333333333
22222222222222
11111111111111
$
sed -n '1!G;h;$p' foo
33333333333333
22222222222222
11111111111111
将模式空间的内容保存到保持空间中去
sed
中的
d
表示删除模式空间。
1!G表示除了第一行以外,其余行都执行G命令;$!d表示除了最后一行以外,其余行都执行d命令。
看一下sed
'1!G;h;$!d'命令执行过程中保持空间与模式空间的变化:
命令
保持空间 模式空间
第一行
h;d
执行前:null
执行后:1111\n
执行前:1111\n
执行后:null
第二行
G;h;d
执行前:1111
执行后:2222\n1111\n
执行前:2222\n
执行后:null
第二行
G;h
执行前:2222\1111\n
执行后:3333\n2222\n\1111\n
执行前:3333\n
执行后:3333\n2222\n\1111\n
*sed工具的多行文本处理操作:
i:
在指定的行之前插入文本a:在指定的行之后追加文本
c:替换指定的行
[root@svr5
~]#
sed '2a
XX'
a.txt
//在第二行后面,追加XX[root@svr5
~]#
sed '2i
XX'
a.txt
//在第二行前面,插入XX[root@svr5
~]#
sed '2c
XX'
a.txt
//将第二行替换为XX
sed
-i
'$a
192.168.4.5 svr5.tarena.com svr5'/etc/hosts
#在最后一行后
追加
r
读取文件
动作结合 -
选项才会存入
否则只会输出
w保存到文件
动作会直接以覆盖 的方式另存为新文件
sed
-r "1r bbb" aaa #读取bbb文件,在aaa文件的第一行后插入bbb文件内容
sed
-r "r bbb" aaa #在aaa文件的每一行后插入
r制定行的用法同p
,加上选项
-i
后
aaa文件即改变
sed
-r "1w bbb" aaa #将aaa文件的第一行写入bbb文件,没有bbb文件会自动创建,
aaa文件不变
r
指定行用法同p
*总结知识点:
sed
[选项]
'条件指令'
文件
*选项:
*-n
屏蔽默认输出
*-r
支持扩展正则
*-i
修改源文件
*条件:
*行号
4
4,5 4~2 4,+10
*/正则/
*指令:
*p
打印
*d
删除
*s
替换s/旧/新/g
*a
追加
*i
插入
*c
替换行
less
cat
grep
egrep
sed
awk
awk
正则匹配条件要放在//内
同sed
匹配条件都是筛选出行然后再对行进行操作,awk中的变量(大括号内的变量)和shell中的不能互相调用,筛选条件的变量可以是shell中的变量
!/bin/bash
用文本编写好的密码和用户创建
read
-p "请输入一个编写好的用户和密码文本名词:"
Wb
a=`awk
'{print $1}' $Wb`
for
i in $a
do
useradd
$i
b=$(awk
'/'$i'/{print
$2}' $Wb)
echo
$b | passwd --stdin $i
done
awk
[选项]
'[条件]{指令}'
文件
支持管道
[root@svr5
~]#
awk '{print
$1,$3}'
test.txt
列和第3列
若未指定分隔符,则默认将空
格、制表符等作为分隔符
awk
-F:'{print
$1,$7}'/etc/passwd
#-F可指定分隔符可以是任意字符串,
分隔符是不可以print的(但
#没有指定输出列
分隔符是可以输出的)
awk
-F
[:/]
'{print $1,$10}' /etc/passwd
#[]中的任意单个字符都是分隔符
*awk常用内置变量:
*$0
文本当前行的全部内容
*$1 文本的第1列
*$2 文件的第2列
*$3 文件的第3列,依此类推
*NR 文件当前行的行号(相当与一个信号,正在处理哪一行即NR就是当前行的行号)
*NF 文件当前行的列数(有几列)
awk
-F:'{print
$1,"的解释器:",$7}'/etc/passwd
ifconfig
eth0 |
awk '/TX
p/{print
$5}'//过滤发送数据的流量#正则匹配所需行
[root@svr5
~]#
df -h
/
文件系统
容量 已用 可用 已用%挂载点
/dev/sda2
19G .2G
11G %/
[root@svr5
~]#
df -h
|
awk '/\/$/{print
$4}' #注意转义/
11G
BEGIN{}
ENG{}
BEGIN{
} 行前处理,读取文件内容前执行,指令执行1次{
} 逐行处理,读取文件过程中执行,指令执行n次END{
} 行后处理,读取文件结束后执行,指令执行1次
awk
[选项]'
BEGIN{指令}
{指令}
END{指令}'文件
[root@server0
~]# awk 'BEGIN{print "a"}'
#输出字符
要用双引号
a
#BEGIN{}处理命令跟文件无关,可以不加处理文件
[root@server0
~]# awk 'BEGIN{print a=1,a}'
#不用双引号
代表引用变量
1
1
[root@server0
~]# awk 'BEGIN{print a=1;print
a}'
1
1
[root@server0
~]# cat aaa
1
2
3
4
[root@server0
~]# awk '{print ++a}' aaa #{}处理命令跟文件有关,逐行匹配,匹配成功便执行命令
1
2
3
4
[root@server0
~]# awk 'END{print 2}' aaa #END{}最后处理
结构同BEGIN{},与文件aaa无关
2
#(但不可以省略aaa因为BEGIN是过滤文件之前操作,而END是过滤文件之后操作
)
awk
'BEGIN{print A=1}{print
A++}END{print
A+1}' aaa #++A A++ 同C语言
1
1
2
3
4
6
[root@server0
~]# awk 'BEGIN{print A=1}{print
++A}END{print
A+1}' aaa
1
2
3
4
5
6
seq
5 | awk '$1%3'
#条件筛选的作用同sed
目的是找出匹配的行
而真假同C语言,0假,非0真
1
2
4
5
seq
5 | awk '$1%3==0'
3
seq
|
awk '$1%7==0||$1~/7/'
列出100以内整数中7的倍数或是含7的数:
[root@svr5
~]#
awk 'BEGIN{x=0}/bash$/{x++}
END{print x}'/etc/passwd
29
使用“\t”显示Tab制表位
[root@svr5
~]#
awk -F:'/^(root|adm)/{print
$1,$3}'/etc/passwd
#输出root或adm账户的用户名和UID
#
信息:
awk
-F:'$1~/root/'/etc/passwd
#输出账户名称包含root的基本信息(第1列匹配包含root)
awk
-F:'$7!~/nologin$/{print
$1,$7}'/etc/passwd
#对第7个字段做!~反向匹配输出其中登录Shell不
#以nologin结尾
*使用数值/字符串比较设置条件
*比较符号:==(等于)
!=(不等于)
>(大于)
*>=(大于等于)
<(小于)
<=(小于等于)
*awk
-F:'NR==3{print}'/etc/passwd
#输出第3行(行号NR等于3)的用户记录:
awk
-F:'$3>=1000{print
$1,$3}'/etc/passwd
awk
-F:'$1=="root"'/etc/passwd
#输出用户名为“root”的行:
awk
-F:'$3>10
&&
$3<20'/etc/passwd
awk
-F:'$3>1000
|| $3<10'/etc/passwd
awk
'BEGIN{x=8;x--;print
x}'
if(条件){指令}
if(条加){指令}else{}
if(条件){指令}else
if{条件}......else{指令}
awk
-F:'{if($3>1000){i++}}END{print
i}'/etc/passwd
#统计/etc/passwd文件中UID大于1000的用户
#
个数:
awk
-F:'{if($3<=1000){i++}else{j++}}END{print
i,j}'/etc/passwd
*awk数组
*1)数组的语法格式
*数组是一个可以存储多个值的变量,具体使用的格式如下:
*定义数组的格式:数组名[下标]=元素值
*调用数组的格式:数组名[下标]
*遍历数组的用法:for(i
in
数组名){print
数组名[变量]}。#i的值是下标
类似python的字典(因为其下标是可以任意定义的字符串(字母数字下划线))
awk
'BEGIN{a[0]=11;a[1]=88;print
a[1],a[0]}'
[root@svr5
~]#
awk 'BEGIN{a[0]=0;a[1]=11;a[2]=22;
for(i in a){print i,a[i]}}'
针对文本排序输出可以采用sort命令,相关的常见选项为-r、-n、-k。其中-n表示按数字顺序升序排列,而-r表示反序,-k可以指定按第几个字段来排序。
[root@room9pc01
~]# cat aaa
a
a
b
b
a
a
a
v
[root@room9pc01
~]# awk '{pi[$1]++} END{for(i in pi){print pi[i],i}}' aaa
#计算文本中相同字段
出现的次数
1
v
5
a
2
b
[root@room9pc01
~]# awk '{pi[$1]++} END{for(i in pi){print pi[i],i}}' aaa | sort -nr
5
a
2
b
1
v