赞
踩
Shell是一个命令行解释器,他接收应用程序/用户命令,然后调用操作系统内核,Shell是一个功能相当强大的编程语言,易于编写,调试,灵活性强。
脚本以#!/bin/bash开头(指定解析器)
首先我们创建一个shell脚本文件:helloworld.sh
#!/bin/bash
echo "helloworld"
保存之后运行
sh执行:
sh helloworld.sh
bash执行:
bash helloworld.sh
绝对路径sh执行:
sh /home/zsb/helloworld.sh
但是./helloworld.sh不行,为什么呢?
因为sh与bash是代替我们去执行,而我们自己执行时会显示没权限,脚本本身不需要执行权限,第二种本质是脚本需要自己执行,所以需要执行权限,我们查看一下文件的权限:
发现没有执行权限,故chmod就可以执行了:
在/home/zsb/目录下创建一个banzhang.txt,在banzhang.txt文件中增加"I love cls"。
#!/bin/bash
cd /home/zsb/
touch banzhang.txt
echo "I love cls" >> banzhang.txt
$HOME、$PWD、$SHELL、$USER等。
[zsb@VM-4-8-centos ~]$ echo $HOME //家目录
/home/zsb
[zsb@VM-4-8-centos ~]$ echo $PWD //当前所处目录
/home/zsb
[zsb@VM-4-8-centos ~]$ echo $SHELL //当前默认shell
/bin/bash
[zsb@VM-4-8-centos ~]$ echo $USER //当前用户
zsb
[root@VM-4-8-centos zsb]# A=1
[root@VM-4-8-centos zsb]# echo $A
1
[root@VM-4-8-centos zsb]# unset A
[root@VM-4-8-centos zsb]# echo $A
[root@VM-4-8-centos zsb]# readonly A=1
[root@VM-4-8-centos zsb]# echo $A
1
[root@VM-4-8-centos zsb]# unset A
bash: unset: A: cannot unset: readonly variable
readonly变量在关掉ssh后自动消除。
[root@VM-4-8-centos zsb]# B = 1
bash: B: command not found
[root@VM-4-8-centos zsb]# B= 1
bash: 1: command not found
[root@VM-4-8-centos zsb]# B=1+1
[root@VM-4-8-centos zsb]# echo $B
1+1
[root@VM-4-8-centos zsb]# B="1 2 3"
[root@VM-4-8-centos zsb]# echo $B
1 2 3
我们在前面的helloworld.sh中编写:
#!/bin/bash
echo "hello world"
echo $B
我们发现打印不出B的值,原因是我们定义的B变量只是局部的,并不是全局的,所以我们可以将B变量提升为全局变量,供我们的helloworld.sh程序使用:
[root@VM-4-8-centos shell_study]# export B
[root@VM-4-8-centos shell_study]# ./helloworld.sh
hello world
1 2 3
此时就打印出来了。
$n: (功能描述:n为数字,$0代表该脚本名称,$1-S9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如S{10})
例如:
parameter.sh:
#!/bin/bash
echo $0 $1 $2 $3
[root@VM-4-8-centos shell_study]# ./parameter.sh
./parameter.sh
[root@VM-4-8-centos shell_study]# ./parameter.sh cls
./parameter.sh cls
[root@VM-4-8-centos shell_study]# ./parameter.sh cls xz
./parameter.sh cls xz
[root@VM-4-8-centos shell_study]# ./parameter.sh cls xz zsb
./parameter.sh cls xz zsb
$# :(功能描述:获取所有输入参数个数,常用于循环)
parameter.sh:
#!/bin/bash
echo $0 $1 $2 $3
echo $#
[root@VM-4-8-centos shell_study]# ./parameter.sh
./parameter.sh
0
[root@VM-4-8-centos shell_study]# ./parameter.sh cls
./parameter.sh cls
1
[root@VM-4-8-centos shell_study]# ./parameter.sh cls cls xz
./parameter.sh cls cls xz
3
$* :(功能描述:这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体)。
$@:(功能描述:这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待)。
parameter.sh:
#!/bin/bash
echo $0 $1 $2 $3
echo $#
echo $*
echo $@
[root@VM-4-8-centos shell_study]# ./parameter.sh cls xz zsb
./parameter.sh cls xz zsb
3
cls xz zsb
cls xz zsb
$?:(功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。)·
[root@VM-4-8-centos shell_study]# ./helloworld.sh
hello world
1 2 3
[root@VM-4-8-centos shell_study]# echo $?
0
[root@VM-4-8-centos shell_study]# $?
bash: 0: command not found
[root@VM-4-8-centos shell_study]# echo $?
127
(1) “$((运算式))”或“$[运算式]”
(2) expr +,-,\*,/, % 加,减,乘,除,取余
注意: expr运算符间要有空格
(1) 计算3+2的值
[root@VM-4-8-centos ~]# expr 3 + 2
5
[root@VM-4-8-centos ~]# echo $((3+2))
5
[root@VM-4-8-centos ~]# echo $[3+2]
5
(2) 计算3-2的值
[root@VM-4-8-centos ~]# expr 3 - 2
1
[root@VM-4-8-centos ~]# echo $((3-2))
1
[root@VM-4-8-centos ~]# echo $[3-2]
1
(3) 计算(2+3)*4的值
[root@VM-4-8-centos ~]# expr `expr 2 + 3` \* 4
20
[root@VM-4-8-centos ~]# echo $(((2+3)*4))
20
[root@VM-4-8-centos ~]# echo $[(2+3)*4]
20
[ condition ] (注意condition前后要有空格),
注意:条件非空即为true,[ atguigu ]返回true,[]返回 false。
= 字符串比较
-lt 小于(less than)
-le 小于等于(less equal)
-eq 等于(equal)
-gt 大于(greater than)
-ge 大于等于(greater equal)
-ne 不等于(Not equal)
-r 有读的权限(read)
-w 有写的权限(write)
-x 有执行的权限(execute)
-f 文件存在并且是一个常规的文件(file)
-e 文件存在(existence)
-d 文件存在并是一个目录(directory)
(1) 23是否大于等于22
[root@VM-4-8-centos ~]# [ 23 -ge 22 ]
[root@VM-4-8-centos ~]# echo $?
0
[root@VM-4-8-centos ~]# [ 23 -le 22 ]
[root@VM-4-8-centos ~]# echo $?
1
0为true,非0为false
(2) helloworld.sh是否具有写权限
[root@VM-4-8-centos shell_study]# [ -w helloworld.sh ]
[root@VM-4-8-centos shell_study]# echo $?
0
(3) /home/zsb/zsb.txt文件是否存在
[root@VM-4-8-centos shell_study]# [ -e zsb.txt ]
[root@VM-4-8-centos shell_study]# echo $?
1
(4) 多条件判断(&&表示前一条命令执行成功时,才执行后一条命令,||表示上一条命令执行
失败后,才执行下一条命令)
条件:helloworld.sh有写权限,zsb.txt文件不存在
[root@VM-4-8-centos shell_study]# [ -w helloworld.sh ] && echo "yes"
yes
[root@VM-4-8-centos shell_study]# [ -w helloworld.sh ] || echo "yes"
[root@VM-4-8-centos shell_study]#
[root@VM-4-8-centos shell_study]# [ -e zsb.txt ] || echo "no"
no
if [ 条件判断式 ]
then
程序
fi
或者
if [ 条件判断式 ];then
程序
fi
注意:
(1) [条件判断式],中括号和条件判断式之间必须有空格。
(2) if后要有空格。
(1) 输入一个数字,如果是1,则输出 班长真帅,如果是2,则输出 班长真丑,如果是其它,什么也不输出。
#!/bin/bash
if [ $1 -eq 1 ]
then
echo "好好学习,进大厂"
elif [ $1 -eq 2 ]
then
echo "不好好学习,回家养猪"
fi
[root@VM-4-8-centos shell_study]# sh if.sh 1
好好学习,进大厂
[root@VM-4-8-centos shell_study]# sh if.sh 2
不好好学习,回家养猪
case $变量名 in
"值1")
如果变量的值签于值1,则执行程序1
;;
"值2")
如果变量的值签于值2,则执行程序2
;;
*)
如果变量的值非值1和值2,则执行该程序
;;
esac
(1) 输入1输出man,输入2输出woman,输入3输出renyao。
#!/bin/bash
case $1 in
1)
echo "man"
;;
2)
echo "woman"
;;
*)
echo "renyao"
;;
esac
[root@VM-4-8-centos shell_study]# sh case.sh 1
man
[root@VM-4-8-centos shell_study]# sh case.sh 2
woman
[root@VM-4-8-centos shell_study]# sh case.sh 3
renyao
for(( 初始值;循环控制条件;变量变化 ))
do
程序
done
(1) 从1加到100
#!/bin/bash
s=0
for((i=1;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
[root@VM-4-8-centos shell_study]# sh for1.sh
5050
for 变量 in 值1 值2 值3...
do
程序
done
(1) 打印所有输入参数
#!/bin/bash
for i in $*
do
echo $i
done
[root@VM-4-8-centos shell_study]# sh for2.sh 1 2 3
1
2
3
while [ 条件判断式 ]
do
程序
done
(1) 从1加到100
#!/bin/bash
i=1
s=0
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s
[root@VM-4-8-centos shell_study]# sh while.sh
5050
read 选项 参数
选项:
-p:指定读取值时的提示符;。
-t:指定读取值时等待的时间(秒)。
参数:
变量:指定读取值的变量名
(1) 在7秒内输入名字,并输出。
#!bin/bash
read -t 7 -p "please input your name: " NAME
echo $NAME
[root@VM-4-8-centos shell_study]# sh read.sh
please input your name: zsb
zsb
basename string/pathname suffix
(功能描述: basename命令会删掉所有的前缀包括最后一个(‘/')字符,然后将字符串显示出来。
选项:
suffix为后缀,如果 suffix被指定了, basename 会将pathname或 string 中的 suffix去掉。
(1) 截取/home/zsb/helloworld.sh路径的文件名称
[root@VM-4-8-centos shell_study]# basename /home/zsb/shell_study/helloworld.sh
helloworld.sh
[root@VM-4-8-centos shell_study]# basename /home/zsb/shell_study/helloworld.sh .sh
helloworld
dirname文件绝对路径
(功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)。
(1) 获取helloworld.sh文件的路径
[root@VM-4-8-centos shell_study]# dirname /home/zsb/shell_study/helloworld.sh
/home/zsb/shell_study
[ function ] funname[()]
{
Action:
[return int;]
}
funname
(1)必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过$?系统变量获得,可以显式加: return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)。
(1) 计算两个输入参数的和
#!/bin/bash
function sum()
{
s=0;
s=$[$1+$2]
echo $s
}
read -p "请输入加数1:" p1
read -p "请输入加数2:" p2
sum $p1 $p2
[root@VM-4-8-centos shell_study]# sh function.sh
请输入加数1:1
请输入加数2:2
3
cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
cut [选项参数] filename
说明:默认分隔符是制表符
-f:列号,提取第几列
-d:分隔符,按照指定分隔符分割列
(1) 切割cut.txt第二列
[root@VM-4-8-centos shell_study]# cut -d " " -f 2 cut.txt
shen
zhen
wo
lai
le
(2) 在cut.txt文件中切割出 jing
[root@VM-4-8-centos shell_study]# cat cut.txt | grep jing
jing zhen
[root@VM-4-8-centos shell_study]# cat cut.txt | grep jing | cut -d " " -f 1
jing
(3) 选取系统PATH变量值,第2个":"开始后的所有路径
[root@VM-4-8-centos shell_study]# echo $PATH
/opt/rh/devtoolset-7/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@VM-4-8-centos shell_study]# echo $PATH | cut -d ":" -f 3-
/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
(4) 切割ifconfig后打印的IP地址
[root@VM-4-8-centos shell_study]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.4.8 netmask 255.255.252.0 broadcast 10.0.7.255
inet6 fe80::5054:ff:fed5:55e2 prefixlen 64 scopeid 0x20<link>
ether 52:54:00:d5:55:e2 txqueuelen 1000 (Ethernet)
RX packets 4646630 bytes 1981270152 (1.8 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3936053 bytes 697389243 (665.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@VM-4-8-centos shell_study]# ifconfig eth0 | grep "inet "
inet 10.0.4.8 netmask 255.255.252.0 broadcast 10.0.7.255
[root@VM-4-8-centos shell_study]# ifconfig eth0 | grep "inet " | cut -d " " -f 10
10.0.4.8
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。,
sed [选项参数] ‘command’ filename
-e :直接在指令列模式上进行sed的动作编辑
a:新增,a的后面可以接字符串,在下一行出现
d:删除
s:查找并替换
sed.txt
bei shen
jing zhen
wo wo
lai lai
le le
(1) 在第二行增加mei nv
[root@VM-4-8-centos shell_study]# sed "2a mei nv" sed.txt bei shen jing zhen mei nv wo wo lai lai le le 并不会改变源文件: [root@VM-4-8-centos shell_study]# cat sed.txt bei shen jing zhen wo wo lai lai le le
(2) 删除sed.txt文件所有包含wo的行
[root@VM-4-8-centos shell_study]# sed "/wo/d" sed.txt
bei shen
jing zhen
lai lai
le le
(3) 将sed.txt文件中wo替换为ni
[root@VM-4-8-centos shell_study]# sed "s/wo/ni/" sed.txt bei shen jing zhen ni wo lai lai le le [root@VM-4-8-centos shell_study]# sed "s/wo/ni/g" sed.txt bei shen jing zhen ni ni lai lai le le //g表示全局,不加g只会替换第一个
(4) 将sed.txt文件中的第二行删除并将wo替换为ni
[root@VM-4-8-centos shell_study]# sed "2d" sed.txt | sed "s/wo/ni/g"
bei shen
ni ni
lai lai
le le
或者:
[root@VM-4-8-centos shell_study]# sed -e "2d" -e "s/wo/ni/g" sed.txt
bei shen
ni ni
lai lai
le le
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
-F:指定输入文件拆分隔符
-v:赋值一个用户定义变量
(0) 数据准备
[root@VM-4-8-centos shell_study]# cp -rf /etc/passwd ./
[root@VM-4-8-centos shell_study]# 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:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin polkitd:x:999:998:User for polkitd:/:/sbin/nologin libstoragemgmt:x:998:997:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin ntp:x:38:38::/etc/ntp:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin chrony:x:997:995::/var/lib/chrony:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin syslog:x:996:994::/home/syslog:/bin/false lighthouse:x:1000:1000::/home/lighthouse:/bin/bash zsb:x:1001:1001::/home/zsb:/bin/bash
(1)搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。
awk -F ":" '/^root/{print $7}' passwd
^root表示以root开头,$root表示以root结尾
[root@VM-4-8-centos shell_study]# awk -F ":" '/^root/{print $7}' passwd
/bin/bash
(2)搜索 passwd 文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。
awk -F ":" '/^root/{print $1","$7}' passwd
[root@VM-4-8-centos shell_study]# awk -F ":" '/^root/{print $1","$7}' passwd
root,/bin/bash
(3) 只显示/etc/passwd 的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell,在最后一行添加"shibingge,/bin/zuishuai"。
[root@VM-4-8-centos shell_study]# awk -F ":" 'BEGIN {print "user,shell"} {print $1","$7} END{print "shibingge,/bin/zuishuai"}' passwd user,shell root,/bin/bash bin,/sbin/nologin daemon,/sbin/nologin adm,/sbin/nologin lp,/sbin/nologin sync,/bin/sync shutdown,/sbin/shutdown halt,/sbin/halt mail,/sbin/nologin operator,/sbin/nologin games,/sbin/nologin ftp,/sbin/nologin nobody,/sbin/nologin systemd-network,/sbin/nologin dbus,/sbin/nologin polkitd,/sbin/nologin libstoragemgmt,/sbin/nologin rpc,/sbin/nologin ntp,/sbin/nologin abrt,/sbin/nologin sshd,/sbin/nologin postfix,/sbin/nologin chrony,/sbin/nologin tcpdump,/sbin/nologin syslog,/bin/false lighthouse,/bin/bash zsb,/bin/bash shibingge,/bin/zuishuai
BEGIN在所有数据读取行之前执行;END在所有数据执行之后执行。
(4) 将passwd文件中的用户id增加数值1并输出
[root@VM-4-8-centos shell_study]# awk -F ":" -v i=1 '{print $3+i}' passwd 1 2 3 4 5 6 7 8 9 12 13 15 100 193 82 1000 999 33 39 174 75 90 998 73 997 1001 1002
FILENAME:文件名
NR:已读的记录数(也就是第几行)
NF:浏览记录的域的个数(也就是切割后,列的个数)
(1) 统计passwd文件名,每行的行号,每行的列数
[root@VM-4-8-centos shell_study]# awk -F ":" '{print FILENAME "," NR "," NF}' passwd passwd,1,7 passwd,2,7 passwd,3,7 passwd,4,7 passwd,5,7 passwd,6,7 passwd,7,7 passwd,8,7 passwd,9,7 passwd,10,7 passwd,11,7 passwd,12,7 passwd,13,7 passwd,14,7 passwd,15,7 passwd,16,7 passwd,17,7 passwd,18,7 passwd,19,7 passwd,20,7 passwd,21,7 passwd,22,7 passwd,23,7 passwd,24,7 passwd,25,7 passwd,26,7 passwd,27,7
(2) 切割IP
[root@VM-4-8-centos shell_study]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.4.8 netmask 255.255.252.0 broadcast 10.0.7.255
inet6 fe80::5054:ff:fed5:55e2 prefixlen 64 scopeid 0x20<link>
ether 52:54:00:d5:55:e2 txqueuelen 1000 (Ethernet)
RX packets 4683407 bytes 1984688896 (1.8 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3972795 bytes 703363499 (670.7 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@VM-4-8-centos shell_study]# ifconfig eth0 | grep "inet " | awk -F " " '{print $2}'
10.0.4.8
(3) 查询sed.txt中空行所在的行号
[root@VM-4-8-centos shell_study]# awk '/^$/{print NR}' sed.txt
5
sort命令是将文件进行排序,并将排序结果标准输出
sort 选项 参数
-n:按照数值的大小排序
-r:以相反的顺序来排序
-t:设置排序时所用的分格字符
-k:指定需要排序的列
(0) 数据准备
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
(1) 按照第2列对数据排序
sort -t : -n -k 2 sort.txt
问题1:使用Linux命令查询file1中空行所在的行号
awk '/^$/{print NR}' file1
问题2:有文件chengji.txt内容如下;
张三 40
李四 50
王五 60
请使用Linux命令计算第二列的和并输出
[root@VM-4-8-centos shell_study]# awk -F " " -v sum=0 '{sum+=$2} END{print sum}' chengji.txt
150
问题1:Shell脚本里如何检查一个文件是否存在?如果不存在该如何处理?
#/bin/bash
if [ -e helloworld.sh ]
then
echo "文件存在!"
else
echo "文件不存在!"
fi
问题1:用shell写一个脚本,对文本中无序的一列数字排序并求和
排序: [root@VM-4-8-centos shell_study]# sort -n test.txt 1 2 3 4 5 6 7 8 9 10 排序并求和 [root@VM-4-8-centos shell_study]# sort -n test.txt | awk -v sum=0 '{sum+=$1;print $1} END{print sum}' 1 2 3 4 5 6 7 8 9 10 55
问题2:请用shell脚本写出查找当前文件夹(/home)下所有文本文件内容中包含有字符"shen"的文件名称
grep -r "shen" /home | cut -d ":" -f 2
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。