Shell脚本之基础-2

目录

 一、字符处理

cut命令

awk命令

sed命令

字符串排序

二、条件判断

文件类型判断

文件权限判断

两个文件的判断

整数比较

字符串判断

多重判断

三、流程控制

if分支

if else 双分支结构

case分支

for循环

while循环


 一、字符处理

cut命令

命令格式: cut [选项] 文件名 

选项:

        -f 列号: 提取第几列 
        -d 分隔符: 按照指定分割符进行分割,默认的分割符是制表符,注意分割符不能使用空格。

示例:

# 每个字段已制表符分割,不能是空格。
[root@localhost ~]# vi person.txt
ID Name sex age
1 ls m 18
2 zs m 25
3 ww w 22
[root@localhost ~]# cut -f 2 person.txt
Name
ls
zs
ww
[root@localhost ~]# cut -f 2,3 person.txt
Name sex
ls m
zs m
ww w
# 指定分割符的示例
[root@localhost ~]# cut -d ":" -f 1,3 /etc/passwd
root:0
bin:1
daemon:2
adm:3
lp:4
...
# 在管道符中使用的例子
[root@localhost ~]# cat /etc/passwd | cut -d ":" -f 1,3
root:0
bin:1
daemon:2
...
# cut的局限性,提取第五列没有作用,因为分隔符是连续的空格,而不是制表符
[root@localhost ~]# df -h | cut -f 5
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 475M 0 475M 0% /dev
tmpfs 487M 0 487M 0% /dev/shm
tmpfs 487M 7.7M 479M 2% /run
tmpfs 487M 0 487M 0% /sys/fs/cgroup
/dev/mapper/centos-root 17G 1.7G 16G 10% /
/dev/sda1 1014M 167M 848M 17% /boot
tmpfs 98M 0 98M 0% /run/user/0
[root@localhost ~]#
# 指定分隔符为空格符也不行,因为不知道到底又几个空格
[root@localhost ~]# df -h | cut -d " " -f 5

awk命令

格式化输出命令:
printf '输出类型输出格式' 输出内容

输出类型:

  • %ns 输出字符串,n表示输出几个字符
  • %ni 输出整数,n表示输出几个数字
  • %m.nf 输出浮点数, m 表示输出的总位数, n 表示小数点的位数
输出格式:
  • \a 输出警告音
  • \b 输出退格键
  • \f 清除屏幕
  • \n 换行
  • \r 回车
  • \t 水平方向 tab
  • \v 垂直方向 tab
[root@localhost ~]# printf %s 1 2 3 4 5
12345[root@localhost ~]#
# 下面的写法不可以,需要用单引号将类型说明引起来,下面又正确的示例
[root@localhost ~]# printf %s %s %s 1 2 3 4 5 6
%s%s123456[root@localhost ~]#
# 1 2 3 最为一组字符的,4 5 6作为一组, 中间没有换行
[root@localhost ~]# printf '%s %s %s' 1 2 3 4 5 6
1 2 34 5 6[root@localhost ~]#
# 输出一组后加一个换行
[root@localhost ~]# printf '%s %s %s\n' 1 2 3 4 5 6
1 2 3
4 5 6
# printf不能和管道符一起使用,如果需要从文件中获取,则可以如下写法:
[root@localhost ~]# printf '%s' $(cat person.txt)
IDNamesexage1lsm182zsm253www22[root@localhost ~]#
# 这样就可以了
[root@localhost ~]# printf '%s\t %s\t %s\t %s\n' $(cat person.txt)
ID Name sex age
1 ls m 18
2 zs m 25
3 ww w 22
# printf经常与awk一起使用
awk命令格式: awk ' 条件 1 { 动作 1} 条件 2{ 动作 2} ...' 文件名
条件:
一般使用关系表达式作为条件
x > 0        x >= 0         x <= 0
动作:
格式化输出,如 printf
流程控制语句
示例:
# 没有指定条件,即输出所有行,动作是使用printf进行格式化输出
[root@localhost ~]# awk '{printf $2 "\t" $4 "\n"}' person.txt
Name age
ls 18
zs 25
ww 22
# print会在行末自动加换行符
[root@localhost ~]# df -h | awk '{print $1 "\t" $5 "\t" $6}'
文件系统 已用% 挂载点
devtmpfs 0% /dev
tmpfs 0% /dev/shm
tmpfs 2% /run
tmpfs 0% /sys/fs/cgroup
/dev/mapper/centos-root 10% /
/dev/sda1 17% /boot
tmpfs 0% /run/user/0
# 使用管道符将多个命令组合使用
[root@localhost ~]# df -h | grep sda1 | awk '{print $5}' | cut -d "%" -f 1
17
# 指定分割符
[root@localhost ~]# awk '{FS=":"} {print $1 "\t" $3}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
#第一行格式不符合要求,
bin 1
daemon 2
adm 3
# 使用begin在读入第一行之前是设置分割符生效
[root@localhost ~]# awk 'BEGIN{FS=":"} {print $1 "\t" $3}' /etc/passwd
root 0
bin 1
daemon 2
# 在输出之前先设置分割符,在输出完后提示一个end
[root@localhost ~]# awk 'BEGIN{FS=":"} END{print "end"} {print $1 "\t" $4}'
/etc/passwd
root 0
bin 1
daemon 2
adm 4
...
end
# 首选读取person文件数据,并传给awk命令,awk命令选取第四列大于等于20的数据(年龄),
# 并格式化输出第二列(名字)
[root@localhost ~]# cat person.txt | awk '$4 >= 20 {print $2 }'
Name
zs
ww

sed命令

适合所有的 Unix linux 平台的轻量级的流编辑器,可以对数据进行选取,替换,删除,新增等操作。
注意: vim 也可以编辑文件,但是不能用来修改命令结果中的内容,如使用管道符将前一个命令的结果
传给 vim 进行处理,这一点 vim 做不到。
命令格式:
sed [ 选项 ] '[ 动作 ]' 文件名
选项:
-n sed 命令会把所用的数据输出到屏幕,使用该选项则只会将 sed 命令处理的行输出到屏幕
-e : 允许对输入数据应用多条 sed 命令编辑
-i sed 的修改结果同步到数据文件中去,而不是屏幕。
动作:
a\: 追加,在当前行后面追加一行或多行
c\: 行替换,用 c 之后的字符串替换原来的数据,替换多行时,除最后一行外,每行需要用 "" 表示数据未
完结
i\: 插入,在当前行之前插入一行或多行,插入多行时,除最后一行外,每行需要用 "" 表示数据未完结
d: 删除指定的行
p: 打印,输出指定的行
s: 字符串替换,格式为: 行范围 s/ 需要替换的字符 / 替换的新字符 /g”
# 2p 代表输出第二行,输出后又会将其他行输出,这是sed的默认行为,如果不想输出其他行
# 则需要使用n参数
[root@localhost ~]# sed '2p' person.txt
ID Name sex age
1 ls m 18
1 ls m 18
2 zs m 25
3 ww w 22
[root@localhost ~]# sed '2p' -n person.txt
1 ls m 18
# 和管道符结合的示例
[root@localhost ~]# cat person.txt | sed '2p' -n
1 ls m 18
# 删除2,3行数据,注意只是在结果中删除,不会在文件中删除,可以使用cat命令进行验证
[root@localhost ~]# sed '2,3d' person.txt
ID Name sex age
3 ww w 22
[root@localhost ~]# cat person.txt
ID Name sex age
1 ls m 18
2 zs m 25
3 ww w 22
# 追加数据,同样不会影响源文件,因为没有使用-i参数
[root@localhost ~]# sed '4a 4\ttq \tn\t23' person.txt
ID Name sex age
1 ls m 18
2 zs m 25
3 ww w 22
4 tq n 23
# 替换第四行(行替换),不会影响原文件
[root@localhost ~]# sed '4c tihuan' person.txt
ID Name sex age
1 ls m 18
2 zs m 25
tihuan
# 指定字符串替换,不会影响原文件
[root@localhost ~]# sed "3s/25/52/g" person.txt
ID Name sex age
1 ls m 18
2 zs m 52
3 ww w 22
# 这下把文件也替换了
[root@localhost ~]# sed -i "3s/25/52/g" person.txt
[root@localhost ~]# cat person.txt
ID Name sex age
1 ls m 18
2 zs m 52
3 ww w 22

字符串排序

命令格式:
sort [ 选项 ] 文件名
选项:
-f 忽略大小写
-n 数值型排序
-r 反向排序
-t 指定分割符,默认为制表符
-k n[,m] 用指定的字段范围排序, 如果不指定 m ,则表示从 n 到行尾。
[root@localhost ~]# sort /etc/passwd
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...
[root@localhost ~]# sort -r /etc/passwd
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
...
# 对passwd文件,使用”:”作为分割符,去第三个字段进行排序,
# 在排序时将第三字段作为数字(不指定-n则默认作为字符排序)
# 上述的作用即:使用uid数字对passwd文件进行排序
[root@localhost ~]# sort -n -t":" -k 3,3 /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
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
统计命令 wc
命令格式: wc [ 选项 ] 文件名
选项:
-l 只统计行数
-w 只统计单词数
-m 只统计单词数
[root@localhost ~]# wc person.txt
4 16 46 person.txt
# 文件有4行,16单词,46个字符
[root@localhost ~]# wc -l person.txt
4 person.txt
# 文件有4行

二、条件判断

文件类型判断

-d
判断指定的目录是否存在
-e
判断文件是否存在,存在即为真
-f
判断普通文件是否存在
-L
判断文件是否存在且为连接文件
示例:
# 判断文件是否存在,存在为0, 不存在为1
[root@localhost ~]# test -e person.txt
[root@localhost ~]# echo $?
0
[root@localhost ~]#
[root@localhost ~]# test -e aba
[root@localhost ~]# echo $?
1
# 出test外,可以使用中括号
[root@localhost ~]# [ -e person.txt ]
[root@localhost ~]# echo $?
0
[root@localhost ~]#
[root@localhost ~]# [ -d /home ] && echo "is directory" || "is not directory"
is directory
[root@localhost ~]# [ -f ./person.txt ] && echo "yes" || echo "no"
yes

文件权限判断

-r
判断文件是否存在且有读权限
-w
判断文件是否存在且有写权限
-x
判断文件是否存在且有执行权限,注意:拥有者,所属组,其他人只用有一个有指定权限就
会返回真,上面的参数也一样
-u
判断文件是否存在且有 SUID 权限
-g
判断文件是否存在且有 SGID 权限
-k
判断文件是否存在且有 SBIT 权限
[root@localhost ~]# [ -r ./person.txt ] && echo "yes" || echo "no"
yes

两个文件的判断

file1 -nt file2
file1 的最后修改时间是否比 file2 新,是在返回真
file1 -ot file2
file1 的最后修改时间是否比 file2 旧,是在返回真
file1 -ef file2
file1 inode 号是否与 file2 的一致,即是否为同一个文件
[root@localhost ~]# touch abc.txt
[root@localhost ~]# [ person.txt -nt abc.txt ] && echo "yes" || echo "no"
no

整数比较

num1 -eq num2
==
num1 -ne num2
!=
num1 -gt num2
>
num1 -lt num2
<
num1 -ge num2
>=
num1 -le num2
<=
[root@localhost ~]# [ 1 -gt 2 ] && echo "yes" || echo "no"
no

字符串判断

-z str
是否为空,为空返回真
-n str
判断是否为非空,非空返回真
str1 == str2
判断是否相等
str1 != str2
判断是否不等
示例:
[root@localhost ~]# name=zs
[root@localhost ~]# [ -z "$name" ] && echo "yes" || echo "no"
no
[root@localhost ~]# [ "abc" == "bcd" ] && echo "yes" || echo "no"
no
[root@localhost ~]# [ "abc" == "abc" ] && echo "yes" || echo "no"
yes

多重判断

判断 1 -a 判断 2
and
判断 1 -o 判断 2
or
! 判断
示例:
[root@localhost ~]# num=100
# 判断num是否存在,且大于200
[root@localhost ~]# [ -n "$num" -a "$num" -gt 200 ] && echo "yes" || echo "no"
no
[root@localhost ~]# num=201
# 判断num是否存在,且大于200
[root@localhost ~]# [ -n "$num" -a "$num" -gt 200 ] && echo "yes" || echo "no"
yes

三、流程控制

if分支

if [ condition ]; then
语句
fi
或者
if [ condition ]
then
语句
fi

示例1 

[root@localhost ~]# vim iftest.sh
#!/bin/bash
#author:test
num=$1
if [ $num -ge 100 ];then
echo ">100"
fi
[root@localhost ~]# vim iftest.sh
#!/bin/bash
#author:test
num=$1
if [ $num -ge 100 ];then
echo ">100"
fi
[root@localhost ~]# chmod 777 iftest.sh
[root@localhost ~]# ./iftest.sh 102
>100
示例 2
#!/bin/bash
# author: tt
# description: 当sda1盘的占用到90%即输出警告信息
rate=$(df -h | grep "/dev/sda1" | awk '{print $5}' | cut -d "%" -f 1)
if [ $rate -ge 90 ]
then
echo "Warning ! /dev/sda1 is full"
fi

if else 双分支结构

if [ condition ]
then
语句
elif [ condition ]; then
语句
else
语句
fi

示例1

[root@localhost ~]# vim iftest02.sh
#!/bin/bash
#author:tt
num=$1
if [ $num -gt 100 ]
then
echo "num > 100"
else
echo "num <= 100"
fi
[root@localhost ~]# chmod 755 iftest02.sh
[root@localhost ~]# ./iftest02.sh 200
num > 100
示例 2
[root@localhost ~]# vim iftest03.sh
#!/bin/bash
read -p "please input a num:" num
if [ $num -gt 10 -a $num -le 100 ]
then
echo "100>=num>10"
exit 1
elif [ $num -gt 100 -a $num -le 1000 ]; then
echo "1000>=num>100"
exit 2
elif [ $num -gt 1000 -a $num -le 10000 ]; then
echo "10000>=num>1000"
exit 3
else
echo "other num"
fi
[root@localhost ~]# chmod 755 iftest03.sh
[root@localhost ~]# ./iftest03.sh
please input a num:1000
1000>=num>100
[root@localhost ~]#

case分支

if elif else 语句一样都是属于分支语句,不同点在于, case 只能判断一种条件关系, if 可以判断多种条
件关系。
case 语法:
case $conditionVar in
"val1" # 注意此处只能有一个条件,不能像 if 那样使用复杂的多条件
若值为 val1 ,则执行这里
;;
"val2")
若值为 val1 ,则执行这里
;;
...
*)
其他变量值则执行这里
;;
esac

示例: 

[root@localhost ~]# vim casetest.sh
#!/bin/bash
# author: tt
# discription: 演示case语法
read -p "please input y/n " -t 30 inchoose
case $inchoose in
"y")
echo "your input is y"
;;
"n")
echo "your input is n"
;;
*)
echo "your input is others "
;;
esac
[root@localhost ~]# chmod 755 casetest.sh
[root@localhost ~]# ./casetest.sh
please input y/n y
your input is y

for循环

1 ) 用法一
for 变量 in 1 2 3 4 ...
do
执行语句
done
示例 1
[root@localhost ~]# vim fortest.sh
#!/bin/bash
# author: tt
# description: for demo
for i in 1 2 3 4 5 6
do
echo $i
done
[root@localhost ~]# chmod 755 fortest.sh
[root@localhost ~]# ./fortest.sh
...
示例 2
[root@localhost ~]# vim fortest2.sh
#!/bin/bash
for ((i=1;i<=100;i++));
do
echo $((i));
done
示例 3
[root@localhost ~]# vim fortest3.sh
#!/bin/bash
for i in $(seq 1 50)
do
echo $(expr $i)
done
示例 4
[root@localhost ~]# vim fortest4.sh
#/bin/bash
for i in {1..50}
do
echo $((i));
done
示例 5
[root@localhost ~]# vim fortest5.sh
#/bin/bash
list="hello shell word";
for str in $list
do
echo $str
done
示例 6:
[root@localhost ~]# vim fortest6.sh
#/bin/bash
for f in /tmp/*;
do
echo $f;
done

while循环

只要满足循环条件则进行循环
格式:
while [ 条件判断 ]
do
语句
done

 示例:

[root@localhost ~]# vim whiletest1.sh
#!/bin/bash
i=1
s=0
while [ $i -le 100 ]
do
s=$((s+i));
i=$((i+1));
done
echo "sum = $s"
until 循环
只有条件满足才退出循环
格式:
until [ 条件 ]
do
语句
done
示例:
[root@localhost ~]# vim untiltest.sh
#/bin/bash
i=0
s=0
until [ $i -gt 100 ]
do
s=$((s+i));
i=$((i+1));
done
echo "sum = $s"

猜你喜欢

转载自blog.csdn.net/weixin_74457789/article/details/137358294