Shell工具| 流程控制
1. 流程控制
if 判断
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格 (2)if后要有空格 [kris@hadoop datas]$ vim if.sh #!/bin/bash if [ $1 -eq "1" ] then echo "one" elif [ $1 -eq "2" ] then echo "two" else echo "other" fi ------------------- #!/bin/bash if [ $1 -eq "1" ]; then echo "one" fi
运算式$[4%2] 和表达式[ 4 -eq 3 ],注意区别
for循环和if的使用
表达式
[kris@hadoop datas]$ vi for.sh
#!/bin/bash
for ((i=0;i<10;i++))
do
if [ $[$i%2] -eq 0 ]
then
echo $i
fi
done
或者这样写:
for ((i=0;i<10;i++))
do
if [ $(($i%2)) = 0 ]; then echo $i
fi
done
[kris@hadoop datas]$ sh for.sh
0
2
4
6
8
#!/bin/bash
for((i=0;i<10;i++))
do
if [ $(($i%2)) = 0 ]; then echo $i
elif [ $(($i%3)) = 0 ]; then echo $i
else echo "我是奇数"
fi
done
case
#!/bin/bash
case $1 in
"1")
echo "Monday"
;;
"2")
echo "Tuesday"
;;
"3")
echo "Wednesday"
;;
"4")
echo "Thursday"
;;
"5")
echo "Friday"
;;
*)
echo "Weekend"
;;
esac
[kris@hadoop datas]$ ./case.sh 3
Wednesday
while循环
[kris@hadoop datas]$ vim while.sh #!/bin/bash i=1 s=0 while [ $i -le 100 ] do s=$[$s+$i] i=$[$i+1] done echo $s [kris@hadoop datas]$ sh while.sh 3333333333 5050
read读取控制台输入
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
变量:指定读取值的变量名
#/bin/bash
read -p "Please input a num in 5 seconds:" a
echo $a
函数function
bash 可以进入子shell,exit是退出来,
source a.sh是在当前shell执行
./a.sh是在子shell中执行的
export 使得当前shell和子shell中定义的变量都起作用
系统函数
basename [string / pathname] [suffix]
(功能描述:basename命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。
[kris@hadoop datas]$ basename /home/kris/datas/while.sh
while.sh
[kris@hadoop datas]$ basename /home/kris/datas/while.sh .sh
while
dirname 文件绝对路径 (功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))
[kris@hadoop datas]$ dirname /home/kris/datas/while.sh
/home/kris/datas
自定义函数
必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。 函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255) #/bin/bash function sum() { s=$echo $s } sum $1 $2 ~ ~ [kris@hadoop datas]$ [kris@hadoop datas]$ sh function.sh 1 3 4
2. shell工具
cut
cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
-f (列号,提取第几列) -d(分隔符,按照指定分隔符分割列) -c (指定具体字符,如5--9个字符)
[root@kris datas]# ifconfig | grep Bcast
inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
[root@kris datas]# ifconfig | grep Bcast | cut -c 11-14
inet
[root@kris ~]# ifconfig | grep Bcast | cut -d : -f 2
192.168.1.100 Bcast
[root@kris ~]# ifconfig | grep Bcast | cut -d : -f 2 | cut -d " " -f 1
192.168.1.100
[root@kris datas]# ifconfig | grep Bcast > temp.log ##### > 是把原来的内容覆盖、>>是在原内容基础上追加;
[root@kris datas]# cat temp.log
inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
[root@kris datas]# cut -d : -f 2 temp.log
192.168.1.100 Bcast
[root@kris datas]# cat temp.log | cut -d : -f 2 #####与上边是的等效的,只是temp.log所放的位置不一样
192.168.1.100 Bcast
[root@kris datas]# ifconfig | grep Bcast | cut -d : -f 2 | cut -d " " -f 3
Bcast
sed
sed按行处理;
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
-e(直接在指令列模式上进行sed的动作编辑;两个修改指令的方式) -i (在文件中直接编辑修改文件)
a(新增,a的后面可以接字串,在下一行出现 '2axxxx' ) d (删除)
s(查找并替换 ‘s/Link/xxxx/’ )
ifconfig | sed '1d' 删除第一行
ifconfig | sed '1,5d' 删除掉前5行
ifconfig | sed '1akris' 在第一行后面(第二行)追加kris
ifconfig | sed 's/Link/XXX/' 查找并替换;注意是区分大小写的,最后的/符号不要忘记了;
ifconfig | sed 's/Link/XXX/' temp.log #并不会改变文件内容
ifconfig | sed -i 's/Link/XXX/' temp.log 加上-i就可以在文件中修改成功了;前提是文件中的内容必须是ifconfig输出内容;
ifconfig | sed '/^ *R/aXXX' 前边有若干个空格,以R开头的
[root@kris datas]# ifconfig | sed -e '/^ *R/aXXX' -e'/^ *T/d'
以R开头的追加XXX,把以T开头的删掉;这是两个式子就不能通过一个式子搞定了,需加-e改变修改方式,只有一个时可以省略;
awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
按行处理,可以对行内的数据进行更细微的操作;
awk [选项参数] ‘pattern1{action1} pattern2{action2}...’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
选项参数:-F(指定输入文件折分隔符)、-v(赋值一个用户定义变量)
cp /etc/passwd ./
[root@kris datas]# cat passwd | awk '/^a/{print}' 把以a开头的打印出来 [root@kris datas]# cat passwd | awk '/^a/{print}' adm:x:3:4:adm:/var/adm:/sbin/nologin avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin apache:x:48:48:Apache:/var/www:/sbin/nologin [root@kris datas]# cat passwd | awk -F : '/^a/{print $1}' //-F指定输入文件折分隔符 adm avahi-autoipd abrt apache [root@kris datas]# cat passwd | awk -F: '/^a/{print $1} /^adm/{print}' 如果匹配到了以a开头就把print $1打印出来; 如果又匹配到了adm就把print整行打印出;
adm
adm:x:3:4:adm:/var/adm:/sbin/nologin
avahi-autoipd
abrt
apache
alex
#如果不写模板它就把所有行都打印出
[root@kris datas]# cat passwd | awk -F : '{print $1}'
......
[root@kris datas]# cat passwd | awk -F: 'BEGIN{print "begin"} {print$1} END{print "end"}'
#begin在数据输入之前先执行BEGIN这个块里边的;END是所有数据处理完了再执行这个块里边的东西;
begin
...
end
[kris@hadoop datas]$ cat 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:sh.....
[root@kris datas]# cat passwd | awk -F: 'BEGIN{sum=0;print "Sum="sum} {sum+=$3} END{print "Sum="sum}' #把第3列的数值加到sum上,对文件的第3列做累加;
Sum=0
Sum=3222
[root@kris datas]# cat passwd | awk -F: 'BEGIN{sum=0;print "Sum="sum} {sum+=$3; print $3"Sum="sum} END{print "Sum="sum}' ###上面求和的过程
[root@kris datas]# which awk
/bin/awk
[root@kris datas]# ll /bin/awk
lrwxrwxrwx. 1 root root 4 9月 3 2013 /bin/awk -> gawk
[root@kris datas]# cat passwd | awk -F: -v sum=0 'BEGIN{print "Sum="sum} {sum+=$3; print $3"Sum="sum} END{print "Sum="sum}' #-v就是引入一个变量
awk的内置变量
[root@kris datas]# cat temp | awk 'BEGIN{sum=0}{sum+=1}/^$/{print sum}' #打印出文件的所有空行的行号,下面这种方法更简单;
[root@kris datas]# cat temp | awk '/^$/{print NR}' #NR就起到sum的作用; 也可这样写: awk '/^$/{print NR}' temp
2
3
5
7
8
10
11
12
[root@kris datas]# awk '/^$/{print FILENAME}' temp ##每列输出文件名
temp
temp
temp
[root@kris datas]# awk -F : '{print NF}' passwd #######NF是按:切割的列数,一共多少列;
7
7
7
...
[root@kris datas]# awk -F: '{print "filename:" FILENAME ", linenumber:" NR ",columns:"NF}' passwd
filename:passwd, linenumber:1,columns:7
filename:passwd, linenumber:2,columns:7
filename:passwd, linenumber:3,columns:7
[root@kris datas]# ifconfig eth0 | grep "inet addr" | awk -F: '{print $2}'
192.168.1.100 Bcast
[root@kris datas]# ifconfig eth0 | grep "inet addr" | awk -F: '{print $2}' | awk -F " " '{print $1}'
192.168.1.100
一个目录下(包括子目录)一共有多少个java文件? 如何取得每一个文件的名称?
[kris@hadoop ~]$ sudo find / -name "*.java"
/root/anaconda3/pkgs/spyder-3.3.2-py37_0/lib/python3.7/site-packages/spyder/utils/tests/data/example.java
/root/anaconda3/lib/python3.7/site-packages/spyder/utils/tests/data/example.java
[kris@hadoop ~]$ sudo find / -name "*.java" | awk -F "/" '{print $NF}' 以/切割,NF这行一共有多少列,如一共8列,$NF表取第8列
example.java
example.java
[kris@hadoop ~]$ basename /opt/module/hive
hive
practice
使用Linux命令查询file1中空行所在的行号 [krs@hadoop101 datas]$ awk '/^$/{print NR}' file1.txt 5
1.有文件chengji.txt内容如下: 张三 40 李四 50 王五 60 使用Linux命令计算第二列的和并输出 [kris@hadoop datas]$ cat chengji.txt | awk -F " " '{sum+=$2} END{print sum}' ######### -F " " $2 分割的列不是从0开始数的,从1开始 150 2.用shell写一个脚本,对文本中无序的一列数字排序 [kris@hadoop datas]$ sort -n text.txt 1 2 3 4 5 6 7 8 9 10
[kris@hadoop datas]$ sort -n text.txt | awk '{sum+=0;print0;print 0} END{print "sum="sum}'
1
2
3
4
5
6
7
8
9
10
sum=55
3 用shell脚本写出查找当前文件夹(/home)下所有的文本文件内容中包含有字符”kris”的文件名称 [kris@hadoop datas]$ grep -r "kris" /home/ | cut -d : -f 1
sort
-n(依照数值的大小排序) 、 -r (以相反的顺序来排序) 、 -t (设置排序时所用的分隔字符) 、 -k(指定需要排序的列)
[root@kris datas]# cat passwd | grep ^a | sort -t : -k 3
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
[root@kris datas]# cat passwd | grep ^a | sort -t : -k 3 -n
adm:x:3:4:adm:/var/adm:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
[root@kris datas]# cat passwd | grep ^a | sort -t : -k 3 -nr
abrt:x:173:173::/etc/abrt:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@kris datas]# sort -t : -nrk 3 sort.sh
bb:40:5.4
bd:20:4.2
cls:10:3.5
xz:50:2.3
ss:30:1.6