文章目录
入门程序
不需要用 分号结尾!
vi test.sh
# 以下是内容
#!/bin/bash
echo "Hello World !"
- 直接执行
- 增加可执行权限
chmod +x a.sh
./a.sh # 当前目录 下一定要加./ <--->而不是a.sh!
echo命令
用于字符串的输出
echo 12345
# 字符串时最好 加双引号""
变量
定义变量,
等于号 左右 不能有空格!
var_name="taobao.com"
使用变量
echo ${var_name}
# 例子
app=ol
echo ${app}
特殊变量
$n
功能描述:n 为数字,$0 代表该脚本名称,$1- 9 代表第一到第九个参数 ∗ ∗ ,十以上的参数,十以上的参数需要 ∗ ∗ 用大括号包含 ∗ ∗ ,如 ∗ ∗ 9 代表第一到第九个参数**,十以 上的参数,十以上的参数需要**用大括号包含**,如** 9代表第一到第九个参数∗∗,十以上的参数,十以上的参数需要∗∗用大括号包含∗∗,如∗∗{10}
$#
功能描述:获取所有输入参数个数
,常用于循环,判断参数的个数是否正确以及
加强脚本的健壮性)
∗ 、 *、 ∗、@
**
∗
∗
∗
−
−
−
>
∗
∗
功能描述
∗
∗
:这个变量代表命令行中所有的参数,
‘
*** --->**功能描述**:这个变量代表命令行中所有的参数,`
∗∗∗−−−>∗∗功能描述∗∗:这个变量代表命令行中所有的参数,‘*把所有的参数看成一个整体 **$@**---> **功能描述**:这个变量也代表命令行中所有的参数,不过
$@把每个参数区分对待`
- ∗ 和 *和 ∗和@ 不被双引号包含,都输出所有参数!
- 被双引号包含时,$会将所有的参数作为一个整体,以“$1
2
…
2 …
2…n”的形式输
出所有参数;$@会将各个参数分开*,以“$1” “ 2 ” … “ 2”…“ 2”…“n”的形式输出所有参数
$?
功能描述:最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一
个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明
上一个命令执行不正确
函数
系统函数
basename
1)基本语法
basename [string / pathname] [suffix] (功能描述:basename 命令会删掉所有的前
缀包括最后一个(‘/’)字符,然后将字符串显示出来。
2)案例实操
截取该/home/atguigu/banzhang.txt
路径的文件名称\
basename /home/dc/banzhang.txt
#banzhang.txt
basename /home/dc/banzhang.txt .txt
#banzhang
dirname
1)基本语法
dirname 文件绝对路径 (功能描述:从给定的包含绝对路径的文件名中去除文件名
(非目录的部分),然后返回剩下的路径(目录的部分))
dirname 可以理解为取文件路径的绝对路径名称
2)案例实操
获取 banzhang.txt
文件的路径。
dirname /home/atguigu/banzhang.txt
#/home/atguigu
自定义函数
shell中 函数的定义格式如下:
[ function ] funname [()]
{
action;
[return int;]
}
示例:
#!/bin/bash
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
函数返回值在
调用该函数后通过 $?
来获得。
当n>=10时,需要使用${n}来获取参数,n为参数个数!
数据类型
字符串
统一使用
双引号 " "
str="this is a string"
双引号的优点:
- 双引号里可以有
变量
- 双引号里可以出现
转义字符
your_name="taobao"
greeting="hello, ${your_name} !"
echo $greeting
获取字符串长度${#s}
string="abcd"
echo ${#string} #输出 4
截取字符串${s:n1:n2},索引从开始
string="taobao is a great site"
echo ${string:1:4} # 输出 unoo
查找
字符出现的位置
expr index
string="taobao is a great site"
#查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):
echo `expr index "$string" io` # 输出 3
数组
用
括号
来表示数组,数组元素用"空格"符号分割开
array_name=(value0 value1 value2 value3)
array_name=(
value0
value1
value2
value3
)
# 单独 定义数组的各个分量,可以 不使用 连续的下标,而且 下标的范围没有限制
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
读取数组
value=${array_name[n]}
#使用 @或* 符号可以获取数组中的所有元素
echo ${array_name[@]}
获取数组的长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
read 读取控制台输入
1)基本语法
read (选项) (参数)
①选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)如果**-t 不加表示一直等待**!!!
②参数
变量:指定读取值的变量名
2)案例实操
提示 7 秒内,读取控制台输入的名称
touch read.sh
vim read.sh
#!/bin/bash
read -t 7 -p "Enter your name in 7 seconds :" N
echo $N
基本运算符
运算符
$((运算式)) 或 $[运算式]
计算(2+3)* 4
的值
S=$[(2+3)*4]
echo $S
算术运算符
if 后必须加
空格
,[ ] 前后必须留个空格
#!/bin/bash
a=10
b=20
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b`
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
if [ $a == $b ]
then
echo "a 等于 b"
fi
if [ $a != $b ]
then
echo "a 不等于 b"
fi
关系运算符
#!/bin/bash
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a 大于 b"
else
echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a 小于 b"
else
echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a 大于或等于 b"
else
echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a 小于或等于 b"
else
echo "$a -le $b: a 大于 b"
fi
布尔运算符
逻辑运算符
字符串运算符
文件权限与类型判断运算符
(1)按照文件权限
进行判断
- -r 有读的权限(read)
- -w 有写的权限(write)
- -x 有执行的权限(execute)
(2)按照文件类型
进行判断 - -e 文件存在(existence)
- -f 文件存在并且是一个常规的文件(file)
- -d 文件存在并且是一个目录(directory)
流程控制
if else判断语句
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
以下实例判断两个变量是否相等:
a=10
b=20
if [ $a == $b ]
then
echo "a 等于 b"
elif [ $a -gt $b ]
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi
for循环
for 后
加空格
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
for ((i=1;i<100;i++))
do
echo $i;
done
case
case 值 in
值1)
command1
command2
...
commandN
;; #表示break
值2)
command1
command2
...
commandN
;;
*) # 表示 都匹配不上,默认的
command1
command2
...
commandN
;;
esac
跳出循环
#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum # 从键盘获取值
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;; #表示break
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done
正则表达式入门
常用特殊字符
cat /etc/passwd | grep dc
就会匹配所有包含 dc的行
^ 匹配一行的开头
$ 匹配一行的结束
. 匹配一个任意的字符
***** 不单独使用,他和上一个字符连用,表示匹配**上一个字符** 0 次或多次
cat /etc/passwd | grep ^a #会匹配出所有 以 a 开头的行
cat /etc/passwd | grep t$ #会匹配出所有 以 t 结尾的行
cat /etc/passwd | grep r..t #会匹配包含 rabt,rbbt,rxdt,root 等的所有行
cat /etc/passwd | grep ro*t #会匹配 rt, rot, root, rooot, roooot 等所有行
# ^ 和 $ 同时出现时,表示只能匹配 ^ 和 $ 之间的内容
/^abc$/ # 只能匹配'abc'
字符区间
(中括号):[ ]
[ ] 表示匹配某个范围内的**一个字符**
,例如
[6,8]------匹配 6 或者 8
[0-9]------匹配一个 0-9 的数字
[0-9]------匹配任意长度的数字字符串
[a-z]------匹配一个 a-z 之间的字符
[a-z] ------匹配任意长度的字母字符串
[a-c, e-f]------匹配 a-c 或者 e-f 之间的任意字符
cat /etc/passwd | grep r[a,b,c]*t #会匹配 rt,rat, rbt, rabt, rbact,rabccbaaacbt 等等所有行
\
表示转义,并不会单独使用。由于所有特殊字符都有其特定匹配模式,当我们想匹配
某一特殊字符本身时(例如,我想找出所有包含 '$' 的行
),就会碰到困难。此时我们就要
将转义字符和特殊字符连用,来表示特殊字符本身,例如
cat /etc/passwd | grep ‘a\$b’ #会匹配所有包含 a$b 的行
注意
需要使用单引号将表达式引起来!!!
文本编辑命令
cut命令
选项与参数:
-d :后面 接分隔字符。与 -f 一起使用;
-f :依据 -d 的分隔字符 将一段信息分割成为数段,用 -f 取出第几段的意思;
-c :以字符 (characters) 的单位取出固定字符区间;
cut -d '分隔字符' -f 选取的列数
echo $PATH|cut -d ':' -f 2 --选取第2列
echo $PATH|cut -d ':' -f 3,5 --选取第3列和第5列
echo $PATH|cut -d ':' -f 3-5 --选取第3列到第5列
echo $PATH|cut -d ':' -f 3- --选取第3列到最后1列
echo $PATH|cut -d ':' -f 1-3,5 --选取第1到第3列还有第5列
sed命令
动作说明:
- a:在指定行后面插入内容
- i:在指定行前面插入内容
- d:删除指定行
- c :替换指定行
- p :打印指定行的数据,通常需要跟
-n
选项搭配使用 - s :替换指定字符,兼容vim的替换语法,例如 1,20s/old/new/gv
a|i:在指定行位置添加行
python@xxx:~/test$ cat testfile
LINUX!
Linux is a free unix-type opterating system.
This is a linux testfile!
Linux test
python@xxx:~/test$ sed -e 2a\newline testfile
LINUX!
Linux is a free unix-type opterating system.
newline
This is a linux testfile!
Linux test
默认情况下-e
参数可以省略
d:删除指定行
nl /etc/passwd | sed '3,$d' #删除第3到最后一行
nl /etc/passwd | sed '2d' #只删除第2行
s:字符串替换
语法:
sed 's/要被取代的字串/新的字串/g'
[root@VM_0_9_centos ~]# ifconfig | grep 'inet '
inet 172.16.0.9 netmask 255.255.240.0 broadcast 172.16.15.255
inet 127.0.0.1 netmask 255.0.0.0
[root@VM_0_9_centos ~]# ifconfig | grep 'inet '|sed 's/^[^0-9]*\([0-9\.]*\).*$/\1/g'
172.16.0.9
127.0.0.1
选项
-i
直接修改文件内容
[root@www ~]# cat regular_express.txt
taobao.
google.
taobao.
facebook.
zhihu-
weibo-
[root@www ~]# sed -i 's/\.$/\!/g' regular_express.txt
[root@www ~]# cat regular_express.txt
taobao!
google!
taobao!
facebook!
zhihu-
weibo-
awk命令
把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理
** $N 代表取 第N列**
1)基本用法
awk [选项参数] ‘/pattern1/{action1} /pattern2/{action2}…’ filename
pattern:表示 awk 在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
2)选项参数说明
-F
指定输入文件分隔符
-v
赋值一个用户定义变量
3)案例实操
(1)数据准备
sudo cp /etc/passwd ./
(2)搜索 passwd 文件以 root 关键字开头的所有行
,并输出该行的第 7 列。
awk -F : '/^root/{print $7}' passwd
#/bin/bash
(3)搜索 passwd 文件以 root 关键字开头的所有行
,并输出该行的第 1 列和第 7 列,
中间以“,”号分割。
awk -F : '/^root/{print $1","$7}' passwd
#root,/bin/bash
注意:
只有匹配了 pattern 的行才会执行 action
(4)只显示/etc/passwd
的以root开头的行
的第一列和第七列,以逗号分割,且在所有行前面添加列名 user, shell
在最后一行添加wozuishuai
awk -F : 'BEGIN{print "user, shell"} /^root/{print $1","$7}
END{print "wozuishuai"} ' passwd
注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行
(5)将 passwd 文件中以root开头的行
的用户 id 增加数值 1 并输出
awk -v i=1 -F : '/^root/{print $3+i}' passwd
必读
[ ] 前后必须
留个空格
if、for、case 后加空格
!!
$(xx)-->取xx命令的结果
DIR_PATH=$(cd $(dirname $1); pwd) # 执行了 两条命令并把结果赋值给DIR_PATH!!
# 获取当前日期
DATE=$(date +%y%m%d) #将 date +%y%m%d的结果赋值给DATE