shell编程笔记一
shell变量
本地变量
readonly variable //将变量variable设置为只读
readonly -p //列出当前制度变量
环境变量
定义:
$HOME/.bash_profile
/etc/profile
export CHINAITLAB="SHENZHEN" //定义一个环境变量
env //查看当前的环境变量
echo $CHINAITLAB //输出变量的值
echo ${CHINAITLAB:+"We change the variable"} //临时改变当前变量的值,前提是变量必须有值
echo ${BIANLIANG:?"NO variable"} //如果变量BIANLIAN有定义则显示变量的值,该变量没有定义则显示NO variable;这种书写格式主要用来检测变量是否存在
echo ${TEST:-"bingo"} //变量没有定义的话输入bingo,如果变量定义了则输出定义值,与上面类似
echo ${GHOST:="bingo"} //定义一个变量负值为bingo
unset GHOST //取消变量,如果设置为readonly则不能取消变量
位置变量 //在运行脚本的时候同时将一个值按顺序附给相应的位置变量
$0 //脚本的名字
$1-$9 //位置参数,示例见script1.sh和script2.sh,运行./script1 a b c d e 将abcde按顺序负值给$1 $2 $3 $4 $5;运行script2.sh ifconfig将把ifconfig传递给位置变量$1,返回ifconfig文件的位置
标准变量
HOME
IFS
LOGNAME
MAIL //当前用户的邮箱位置
MAILCHECK //每隔多少秒检查是否有新邮件
MAILPATH
TERM //终端类型
PATH //执行命令时要查找的目录
PS1 //[root@rhce ~]#的登陆样式由PS1定义
PS2 //定义了>允许命令分行输入
SHELL
MANPATH //获得帮助文件的位置
TERMINFO //终端信息
特殊变量 //示例见script3.sh
$# //传递脚本参数的个数
$* //以单字符串显示所有向脚本传递的参数
$$ //脚本当前运行的ID号
$! //后台运行的最后一个进程的ID号
$@ //与$#相同,返回形式不一样
$- //与set命令功能相同
$? //显示命令退出的状态,0表示没有错误,其他任何值表示有错误
影响变量的命令
declare //设置或显示变量
-f //只显示函数名
-r //创建只读变量
-x //创建转出变量
-i //创建整数变量
export //显示和创建环境变量
shift //用于移动位置变量,示例见script4.sh
-n //移动n位,如果n=1 则$1=$2,$2=$3 ...依次类推
命令与符号
引号
在双引号内的变量和转义字符可以被解释
单引号内的所有内容都被当作字符串
反引号内的内容被当作命令执行
运算符 //见script5.sh
按位运算符: ^,<<,>>,&,|,~
~ 反运算符,将二进制的0变为1,1变为0
>> 右移运算符,对操作符中的二进制位进行移位操作,忽略最右端一位,左端补零
<< 左移运算符,同上
& 与运算符,比较二进制位,相同位同为1时运算结果为1,其他情况为0
| 或运算符,比较二进制位,相同位只要有一方为1运算结果为1,其他为0
^ 异或运算符,比较二进制位,相同位只要不同时为0或同时为1运算结果就为1,其他情况为0
逻辑与算符
&& 与运算
|| 或运算
赋值与算符
= += -= *= /=
echo -e //解释转义字符
转义字符 \c 回车不换行 \f \t 输入tab键 \n 回车换行
echo -n //回车但是不换行
read语句的命令格式 //script6.sh
read variable1 varialble2
cat -v //显示控制符
grep -v "content" //过滤字符串content
tee -a file //将输出的一个副本输出到屏幕,另一个
文件重定向
command << delimiter //从标准输入中读入,直到遇到delimiter分界符
command < &m //
command > &m //
command < &- //
exec command //重新启动一个shell,原来的shell被关闭,只有对文件描述符3-9操作时才不覆盖当前shell
流程控制
if语句 //示例见script7.sh
if 条件1 //如果条件1成立
then //就执行命令1
命令1
elif 条件2 //如果条件1不成立,条件2成立
then //就执行命令2
命令2
else //命令1和命令2都不成立
命令3 //就执行命令3
fi //if结束
test测试 //示例见script8.sh
! 表达式 //表达式的值为假
表达式1 -a 表达式2 //两个表达式都为真时才返回真
表达式1 -o 表达式2 //两个表达式有一个为真就返回真
[-n] 字符串 //返回字符串的长度
-z 字符串 //字符串长度为0时返回真
字符串1 = 字符串2 //判断两个字符串相等时为真
字符串1 != 字符串2 //判断两个字符串不等时为真
整数1 -eq 整数2 //两个整数是否相等
整数1 -ge 整数2 //整数1大于等于整数2时为真
整数1 -gt 整数2 //整数1大于整数2时为真
整数1 -le 整数2 //整数1小于等于整数2时为真
整数1 -lt 整数2 //整数1小于整数2时为真
整数1 -ne 整数2 //整数1不等于整数2时为真
文件1 -ef 文件2 //文件1和文件2的大小相等时为真
文件1 -nt 文件2 //文件1和文件2的大小不相等时为真
文件1 -ot 文件2 //文件1创建的时间早于文件2时为真
-b 文件 //文件为块文件时为真
-c 文件 //文件为字符文件时为真
-d 文件 //文件为目录文件时为真
-f 文件 //文件存在并且为普通文件时为真
-e 文件 //文件存在时为真
-g 文件 //文件存在并且设置了setgid位时为真
-G 文件 //文件存在并且设置了有效的setgid位时为真
-k 文件 //文件存在并且设置了sticky位时为真
-L 文件 //文件存在并且是符号链接时为真
case语句 //示例见script11.sh case
case 值 in
值1)
命令1
;;
值2)
命令2
;;
esac
for循环 //见示例script12.sh
for 变量名 in 列表
do
命令1
命令2
...
done
until循环 //示例见script13.sh
until 条件
do
命令1
命令2
...
done
while 循环 //示例见script14.sh
while
do
命令1
命令2
...
done
循环控制break和continue //示例见script15.sh,script16.sh
break n //跳出第n层循环
continue n //继续第n层循环
文本过滤
正则表达式
字符 含义
^ 只匹配行首
$ 只匹配行尾
* 匹配0或多个单字符
[] 匹配[]内的一个或多个字符
/ 用来屏蔽一个原字符
. 用来匹配任意单字符
pattern\{n\} 用来匹配前面pattern出现的次数,n为次数
pattern\{n,\} 用来匹配前面pattern出现的次数,次数至少为n
pattern\{n,m\} 用来匹配前面pattern出现的次数,次数至为n与m之间
正则表达式用到的命令
find 命令格式
find path -options [-print -exec -ok]
举例
find -name "hello*" -print //查找当前目录下面以hello开头的文件
find /etc -name "[A-Z]*" -print //查找/etc目录下以A到Z中任何一个字母开头的文件
find / -perm 755 -print //查找根目录下面权限为755的文件
find /home -user root -print //查找home目录下root用户所有的文件
find /home -group root -print //查找home目录下文件属组为root的文件
find /home -nouser -print //查找home目录下文件属主不存在的文件
find `pwd` -nouser -print //同上,使用pwd命令获得当前目录
find /home -nogroup -print //查找home目录下文件属组不存在的文件
find /var -mtime -1 -print //查找最近1天内改变的文件
find /etc -type d -print //查找etc目录下的目录文件
find /usr/bin -type l -print //查找usr/bin目录下的链接文件
find /etc -size +1000000c -print //查找etc目录下大于1m的文件
find /etc -size -1000000c -print //查找etc目录下小于1m的文件
find /etc -size +10 -print //查找etc目录下大于10个block的文件
find /etc -size -10 -print //查找etc目录下小于10个block的文件
find /home -mtime +10 -exec rm -rf {} \; //删除home目录下10天前的文件
find /usr/bin -perm -7 |xargs chmod o-w //查找usr/bin目录下属主权限为7的文件,让其他用户不具备写权限
grep命令
参数
-i //忽略大小写
-n //显示匹配行及行号
-c //只显示有多少个匹配行
-v //过滤掉某些信息
举例
grep "hello" *.txt //在所有的txt文件中查找包含有hello字符串的文档名
grep -c "2004" myfile //在myfile中有多少行存在数字2004,只返回行数
grep -n "2004" myfile //同上,但显示行号
grep -i "HELLO" hello.sh //在hello.sh文件中查找HELLO,不区分大小写
grep -v "2004:22" myfile //过滤掉包含2004:22的行
grep "^[^d]" myfile //查找myfile中开头不为d的行
grep "4\{2\}" myfile //查找myfile中包含连续两个4的行
grep "4\{2,5\}" myfile //查找myfile中包含连续的2到5个4的行
grep "^$" myfile //查找myfile中的空行,^代表行首,$代表行尾
grep "5[[:digit:]][[:digit:]]" myfile //在myfile中查找500到599的数字所在的行,[[::]]中的内容含义如下
类 等价的正则表达式
[[:upper:]] [A-Z]
[[:alnum:]] [0-9a-zA-Z]
[[:lower:]] [a-z]
[[:space:]] 空格或tab
[[:digit:]] [0-9]
[[:alpha:]] [a-zA-Z]
grep "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" //查找有ip地址出现的行
awk工具
参数
$n 代表域号,n=1~?
-F 定义域分隔符
-f 调用awk脚本
~ 匹配
!~ 不匹配
// 匹配或不匹配的内容放到//之间
举例
awk '{print $2}' score.txt |tee score.out //输出score.txt的第二列,并将结果输出到score.out文件和屏幕
awk -F | '{print $4}' score.txt |tee scire.out //输出score.txt的第五列,各列以|作为分隔符
awk '{print "hello_________________world"}' //在屏幕上输出hello___________________world
cat messages |awk '$0 ~ /218.98.157.101/' //在messages文件中查找所有匹配218.98.157.101的行,$0表示所有行
sed编辑器 //该编辑器不对初始文本作操作,他的操作对象是初始文本的一个副本
参数
-n 不打印不匹配的输出结果
-f 调用sed脚本文件
使用行号进行文本查询
x 行号
x,y 行号范围
/pattern/ 包含模式的行
/pattern/pattern/ 包含两个模式的行
pattern/,x 在给定的行号上查询包含模式的行
x,/pattern/ 通过行号和模式查询匹配行
x,y! 查询不包含指定行号x和y的行
命令
p 打印匹配行
= 显示文件行号
a\ 在定位行号后附加新文本信息
i\ 在定位行号后插入新文本信息
d 删除定位行
c\ 用新文本替代定位行
s 用指定模式替换原有模式
r 从另一个文件中读文本
w 将文件写入一个文本
q 第一个模式匹配完成后推出或立即退出
l 显示与八进制ASCⅡ代码等价的控制字符
{} 在定位行执行的命令组
n 从另一个文件中读文本下一行,并附加在下一行
g 将模式2粘贴到/pattern n/
y 传送字符
举例
sed -n '2p' hello.txt //打印hello.txt文件的第二行;2:x,p:打印匹配行
sed -n '1,4p' hello.txt //打印hello.txt文件的第1到第4行
sed -n '/hello/p' hello.txt //打印hello.txt中包含hello文本的行,/hello/:模式匹配
sed -n '4,/hello/p' hello.txt //打印从第4行开始到存在文本hello行的中间行
sed -n '/hello/,5' hello.txt //打印从存在文本hello行到第5行之间的所有行
sed -n '/^$/p' hello.txt //打印文件中的空行
sed -n '/^$/=' hello.txt //显示空行的行号
sed -n -e '/^$/p' -e '/^$/=' hello.txt //打印空行并显示空行的行号,两个命令同时使用时要用-e参数
sed '/hello/i\hi' hello.txt //在匹配字符hello的上面插入hi
sed '/hello/a\hi' hello.txt //在匹配字符hello的下面插入hi
sed '/nihao/c\hello' hello3.txt >hello4.txt //用hello替换nihao
sed '/hello/& hi/p' hello.txt //在匹配字符hello的后面插入hi并打印,&代指模式hello
sed '/hello/hi &/p' hello.txt //在匹配字符hello的前面插入hi并打印
sort命令 //文件排序,sort不对源文件进行操作
格式
sort [options] files
参数
-c 测试文件是否已经分类
-m 合并两个分类文件
-u 删除所有复制行
-o 存储sort结果的输出文件名
-t 域分隔符;用非空或tab键分隔域
+n 从第n个域开始分类,注:第一个域起始编号为0
n 指定分类是域上的数字分类项
-r 逆序排列
举例
sort -c file //检查文件是否排序
sort -u file //合并文件中的重复行
sort -r file //对文件中的内容进行逆序排列
sort -t "." +2 file //按第2个域的内容进行排序,域分隔符为.按阿斯克码排序
sort -t "." +2n file //按第2个域的内容进行排序,域分隔符为.按数字大小排序
uniq命令
参数
-u 只显示不重复的行
-d 只显示有重复数据行
-c 打印每一重复行出现的次数
-f n 忽略前n个域
举例
uniq -c file //打印file中每一行的内容和出现的次数
uniq -d file //只打印有重复的行
uniq -f 2 file //忽略前2个域只比较第2个域以后的内容
sort和uniq经常联合使用 sort file|uniq -c
join命令 合并文件
split命令 分割文件
split -output_file-size input_filename output_filename
函数 //示例见script17.sh script18.sh,script20.sh script21.sh
格式
函数名 ()
{
命令1
...
}
function 函数名 ()
{
命令1
命令2
...
}
shift //改变位置参数的位置,示例见script19.sh
getopts //自定义命令参数,示例见script22.sh
格式
getopts 参数 OPTION