# 井号
这几乎是个shell满场都有的符号,用在shell脚本的开头,如"#!/bin/bash" 井号也常出现在一行的开头,或者位于完整指令之后,这类情况表示符号后面的是注解文字,不会被执行。
由于这个特性,当临时不想执行某行指令时,只需在该行开头加上 # 就行了。这常用在撰写过程中。
如果被用在指令中,或者引号双引号括住的话,或者在倒斜线的后面,那他就变成一般符号,不具上述的特殊功能。
~ 用户家目录
算是个常见的符号,代表使用者的 home 目录:cd ~;也可以直接在符号后加上某帐户的名称:cd ~user或者当成是路径的一部份:~/bin
~+ 当前的工作目录,这个符号代表当前的工作目录,她和内建指令 pwd的作用是相同的。
[root@VM_16_9_centos ~]# pwd
/root
[root@VM_16_9_centos ~]# echo ~+/var/log
/root/var/log
~- 上次的工作目录,这个符号代表上次的工作目录。
[root@VM_16_9_centos ~]# pwd
/root
[root@VM_16_9_centos ~]# echo ~+/var/log
/root/var/log
[root@VM_16_9_centos ~]# echo ~-/etc/httpd/logs
/root/test/etc/httpd/logs
; 分号
在 shell 中,担任"连续指令"功能的符号就是"分号"。譬如以下的例子:
[root@VM_16_9_centos ~]# mkdir test;cd test;echo "safd" >test1;cat test1;pwd
safd
/root/test
;; 连续分号
专用在 case 的选项,担任 Terminator 的角色。
[root@localhost ~]# cat a.sh
#!/bin/bash read -p "please write:" fop case ${fop} in
help)
echo "Usage: Command -help -version filename";;
version)
echo "version 0.1" ;;
esac [root@localhost ~]# sh a.sh
please write:help
Usage: Command -help -version filename
. 点号 (dot,就是“点”)
在 shell 中,使用者应该都清楚,一个 dot 代表当前目录,两个 dot 代表上层目录。
[root@ss-server ~]# cd /usr/local/src/
[root@bz3aomsmsap1002 src]# cd ../
[root@bz3aomsmsap1002 local]# pwd
/usr/local [root@ss-server ~]# cd /usr/local/src/
[root@bz3aomsmsap1002 src]# cd ../../
[root@bz3aomsmsap1002 usr]# pwd
/usr
如果档案名以 dot 开头,该档案就属特殊档案,用 ls指令必须加-a 选项才会显示(即查看隐藏文件)。除此之外,在 regularexpression 中,一个 dot 代表匹配一个字元。
' ' 单引号 (single quote)
被单引号用括住的内容,将被视为单一字串。在引号内的代表变数的$符号,没有作用,也就是说,他被视为一般符号处理,防止任何变量替换。
[root@localhost ~]# heyyou=homeecho
[root@localhost ~]# echo '$heyyou'
$heyyou
" " 双引号 (double quote)
被双引号用括住的内容,将被视为单一字串。它防止通配符扩展,但允许变量扩展。这点与单引数的处理方式不同。
[root@VM_16_9_centos ~]# heyyou=homeecho
[root@VM_16_9_centos ~]# echo ${heyyou}
homeecho
[root@VM_16_9_centos ~]# echo '${heyyou}'
${heyyou}
[root@VM_16_9_centos ~]# echo "${heyyou}"
homeecho
`` 倒引号,相当于$(),表示命令替换,将里面命令执行结果传给变量参数。
在前面的单双引号,括住的是字串,但如果该字串是一列命令列,会怎样?答案是不会执行。要处理这种情况,我们得用倒单引号``来做。
[root@VM_16_9_centos ~]# fdv=`date +%F`
[root@VM_16_9_centos ~]# echo "Today $fdv"
Today 2019-11-28
在倒引号内的 date +%F 会被视为指令,执行的结果会带入 fdv 变数中。
, 逗点 (标点中的逗号)
这个符号常运用在运算当中当做"区隔"用途。如下例:
[root@VM_16_9_centos ~]# cat a.sh
#!/bin/bash
let "t1 = ((a = 5 + 3, b = 7 - 1, c = 15 / 3))"
echo "t1= $t1, a = $a, b = $b"
[root@VM_16_9_centos ~]# sh a.sh
t1= 5, a = 8, b = 6
/ 斜线
在路径表示时,代表目录。
[root@VM_16_9_centos ~]# cd /etc/rc.d
[root@VM_16_9_centos rc.d]# cd ../..
[root@VM_16_9_centos /]#
通常单一的 / 代表 root 根目录的意思;在四则运算中,代表除法的符号。
[root@VM_16_9_centos ~]# let "num1 = ((a = 10 / 2, b = 25 / 5))"
[root@VM_16_9_centos ~]# echo ${num1}
5
\\ 双倒斜线 和 \ 单倒斜线
\\ 双倒斜线:放在指令前,有取消 aliases的作用
=======================================
[root@localhost ~]# alias kevin="ls"
[root@localhost ~]# kevin
a anaconda-ks.cfg
[root@localhost ~]# kevin -l
total 4
-rw-r--r-- 1 root root 0 Nov 28 22:56 a
-rw-------. 1 root root 1850 Oct 22 12:11 anaconda-ks.cfg [root@localhost ~]# \\kevin
-bash: \kevin: command not found [root@localhost ~]# \\kevin -l
-bash: \kevin: command not found \ 单倒斜线:放在特殊符号前,则该特殊符号的作用消失。即转义符号
=======================================
[root@VM_16_9_centos ~]# bkdir=/home
[root@VM_16_9_centos ~]# echo "this is ${bkdir}"
this is /home
[root@VM_16_9_centos ~]# echo "this is \${bkdir}"
this is ${bkdir}
[root@VM_16_9_centos ~]# echo \"this is ${bkdir}\"
"this is /home"
[root@VM_16_9_centos ~]# echo \"this is \${bkdir}\"
"this is ${bkdir}"
| 管道 (pipeline)
pipeline 是 Linux系统中基础且重要的观念。连结上个指令的标准输出,做为下个指令的标准输入。
[root@VM_16_9_centos ~]# who
root pts/0 2019-11-28 22:49 (115.171.60.14)
root pts/1 2019-11-28 23:01 (115.171.60.14)
[root@VM_16_9_centos ~]# who | wc -l
2
善用这个观念,对精简 script 有相当的帮助。
! 惊叹号(negate or reverse)
通常它代表反逻辑的作用,譬如条件侦测中,用 != 来代表"不等于"
[root@VM_16_9_centos ~]# cat a.sh
#!/bin/bash if [ "$?" != 0 ];then
echo "Executes error"
exit 1
fi
[root@VM_16_9_centos ~]# sh a.sh
"Executes error"
在规则表达式中她担任 "反逻辑" 的角色
[root@VM_16_9_centos ~]# touch bo{0,1,2,3,4,5,6,7,8,9}
[root@VM_16_9_centos ~]# ls
bo0 bo1 bo2 bo3 bo4 bo5 bo6 bo7 bo8 bo9
[root@VM_16_9_centos ~]# ls bo{0,1,2,3}
bo0 bo1 bo2 bo3
[root@VM_16_9_centos ~]# ls bo[0-3]
bo0 bo1 bo2 bo3 显示除了bo0-bo3之外的其他文件
[root@VM_16_9_centos ~]# ls bo[!0-3]
bo4 bo5 bo6 bo7 bo8 bo9 显示除了bo5-bo8之外的其他文件
[root@VM_16_9_centos ~]# ls bo[!5-8]
bo0 bo1 bo2 bo3 bo4 bo9
: 内奸指令
在 bash 中,这是一个内建指令:"什么事都不干",但返回状态值 0。
什么都不干,返回状态值 0
[root@VM_16_9_centos ~]# echo $?
0 [root@VM_16_9_centos ~]# : > a.txt
上面这一行,相当于
[root@VM_16_9_centos ~]# cat /dev/null >a.xtt
不仅写法简短了,而且执行效率也好上许多。
? 问号
在文件名扩展(Filename expansion)上扮演的角色是匹配一个任意的字元,但不包含 null 字元。
[root@VM_16_9_centos ~]# ls
a12e.txt aae_txt agte.txt akte.txt aste.txt
[root@VM_16_9_centos ~]# ls a?te.txt
agte.txt akte.txt aste.txt
[root@VM_16_9_centos ~]# ls a1?e.txt
a12e.txt
[root@VM_16_9_centos ~]# ls aae?txt
aae_txt
善用她的特点,可以做比较精确的档名匹配。
* 任意个任意字符。任意的单个或多个字符
相当常用的符号。在文件名扩展(Filename expansion)上,她用来代表任何字元,包含 null 字元。
[root@VM_16_9_centos ~]# ls
a12e.txt aae_txt agte.txt akte.txt a.sh aste.txt
[root@VM_16_9_centos ~]# ls a*e.txt
a12e.txt agte.txt akte.txt aste.txt
[root@VM_16_9_centos ~]# ls a*te.txt
agte.txt akte.txt aste.txt 在运算时,它则代表 "乘法"。
[root@VM_16_9_centos ~]# let "fmult=2*3"
[root@VM_16_9_centos ~]# echo ${fmult}
6 除了内建指令 let,还有一个关于运算的指令expr,星号在这里也担任"乘法"的角色。不过在使用上得小心,他的前面必须加上escape字元(即转义符)。
[root@VM_16_9_centos ~]# expr 2 \* 3
6
** 次方运算
[root@ss-server ~]# let sum=2**4
[root@ss-server ~]# echo ${sum}
16
[root@ss-server ~]# echo $((3*3))
9
[root@ss-server ~]# let sum=2**4
[root@ss-server ~]# echo ${sum}
16
[root@ss-server ~]# echo $((3**3))
27
[root@ss-server ~]# echo $[3**4]
81
$ 变量符号、正则里表示"行尾"
$是变量替换的代表符号。
[root@ss-server ~]# var="wang lao hu"
[root@ss-server ~]# echo $var
wang lao hu
[root@ss-server ~]# echo ${var}
wang lao hu 另外:
在Regular Expressions里被定义为 \"行\" 的最末端。这个常用在grep、sed、awk 以及 vim(vi) 当中。 ^ 表示行首
$ 表示行尾
${} 变量的正规表达式
bash 对 ${} 定义了不少用法,如下,具体说明可参考: https://www.cnblogs.com/kevingrace/p/5996133.html
${parameter:-word} ${parameter:=word} ${parameter:?word} ${parameter:+word} ${parameterffset} ${parameterffset:length} ${!prefix*} ${#parameter} ${parameter#word} ${parameter##word} ${parameter%word} ${parameter%%word} ${parameter/pattern/string} ${parameter//pattern/string}
$* 所有引用的变量
$* 引用script的执行引用变量,引用参数的算法与一般指令相同,指令本身为0,其后为1,然后依此类推。引用变量的代表方式如下:
$0, $1, $2, $3, $4, $5, $6, $7, $8, $9, ${10}, ${11}.....
个位数的,可直接使用数字,但两位数以上,则必须使用 {} 符号来括住。 具体使用含义后面有详细说明
$* 则是代表所有引用变量的符号。使用时,得视情况加上双引号。
[root@ss-server ~]# echo "$*"
""
[root@ss-server ~]# echo "$*" [root@ss-server ~]# cat test.sh
#!/bin/bash
USER=$1
AGE=$2
ADD=$3
HE=$4 echo "$1 is $2,come from $3,and $4"
echo "$*" [root@ss-server ~]# sh test.sh 张阳 20 安徽 帅气
张阳 is 20,come from 安徽,and 帅气
张阳 20 安徽 帅气
$@ 所有引用的变量
$@ 与 $* 具有相同作用的符号,不过它们两者有一个不同点。
符号 $* 将所有的引用变量视为一个整体。但符号 $@ 则仍旧保留每个引用变量的区段观念。 [ $@ 与 $* 二者的区别在下面会详细提到]
$# 参数变量的总数量
这也是与引用变量相关的符号,它的作用是告诉你,引用变量的总数量是多少。
[root@ss-server ~]# cat a.sh
#!/bin/bash
USER=$1
AGE=$2
ADD=$3
HE=$4 echo "$1 is $2,come from $3,and $4"
echo "$*"
echo "$@"
echo "$#"
[root@ss-server ~]# sh a.sh 黄涛 30 杭州
黄涛 is 30,come from 杭州,and
黄涛 30 杭州
黄涛 30 杭州
3
[root@ss-server ~]# echo "$#"
"0"
[root@ss-server ~]# echo "$#"
0
$? 状态值 (status variable)
一般来说,Linux 系统的进程以执行系统调用exit()来结束的。这个回传值就是status值。回传给父进程,用来检查子进程的执行状态。
一般指令程序倘若执行成功,其$?回传值为 0;若执行失败,则$?回传值为 1。
[root@ss-server ~]# ls a.sh
a.sh
[root@ss-server ~]# echo $?
0
[root@ss-server ~]# ls aa.sh
ls: cannot access aa.sh: No such file or directory
[root@ss-server ~]# echo $?
2
$$ 当前shell的PID
由于进程的ID是唯一的,所以在同一个时间,不可能有重复性的 PID。有时,script会需要产生临时文件,用来存放必要的资料。而此script亦有可能在同一时间被使用者们使用。在这种情况下,固定文件名在写法上就显的不可靠。唯有产生动态文件名,才能符合需要。符号$$或许可以符合这种需求。它代表当前shell 的 PID。
[root@ss-server ~]# echo "hello world"
hello world
[root@ss-server ~]# echo $$
78520
[root@ss-server ~]# echo "hello world" > aa.$$
[root@ss-server ~]# cat aa.78520
hello world [root@ss-server ~]# cat a.sh
#!/bin/bash
USER=$1
AGE=$2
ADD=$3
HE=$4 echo "$1 is $2,come from $3,and $4"
echo "$#"
echo "$*"
echo "$@"
echo "$$"
echo "$0"
[root@bz3aomsmsap1002 ~]sh a.sh 张阳 20 安徽 帅气
张阳 is 20,come from 安徽,and 帅气
4
张阳 20 安徽 帅气
张阳 20 安徽 帅气
90261
a.sh
使用它来作为文件名的一部份,可以避免在同一时间,产生相同文件名的覆盖现象。
基本上,系统会回收执行完毕的 PID,然后再次依需要分配使用。所以 script 即使临时文件是使用动态档名的写法,如果script 执行完毕后仍不加以清除,会产生其他问题。
( ) 指令群组 (command group)
用括号将一串连续指令括起来,这种用法对 shell 来说,称为指令群组。如下面的例子:
[root@ss-server ~]# (cd ~ ; pwstr=`pwd` ;echo ${pwstr})
/root
指令群组有一个特性,shell会以产生 subshell来执行这组指令。因此,在其中所定义的变数,仅作用于指令群组本身。来看个例子:
[root@ss-server ~]# cat a.sh
#!/bin/bash
a=wang
b=zhang
(a=han ; echo -e "\n $a \n")
(b=xiaoru; echo -e "this is $b")
echo $a
echo $b [root@ss-server ~]# sh a.sh han this is xiaoru
wang
zhang 由上面可知:shell的指令群组所定义的变数,仅作用于指令群组本身。 来看看echo的几个操作效果
=============================================================
[root@ss-server ~]# echo "aa"
aa
[root@ss-server ~]# echo \"aa\"
"aa"
[root@ss-server ~]# echo -e "\n wang \n" wang [root@ss-server ~]# echo -e \"\n wang \n\" # 这种情况下,\n就不是换行符了,因为双引号也被转义了。
"n wang n"
除了上述的指令群组,括号也用在 array数组变数的定义上;另外也应用在其他可能需要加上escape字元才能使用的场合,如运算式。
(( ))
这组符号的作用与 let 指令相似,用在算数运算上,是 bash 的内建功能。所以,在执行效率上会比使用 let指令要好许多。
[root@ss-server ~]# cat a.sh
#!/bin/bash (( a = 10 ))
echo -e "inital value, a = $a\n" (( a++))
echo "after a++, a = $a" [root@ss-server ~]# sh a.sh
inital value, a = 10 after a++, a = 11
请记住:
$(())、$[] 这两个效果是一样的,都是运算符号,显示运算结果。
let 也是运算符号,设置运算
[root@ss-server ~]# echo $((4*9))
36
[root@ss-server ~]# echo $[4*9]
36
[root@ss-server ~]# let a=4*9
[root@ss-server ~]# echo $a
36
[root@ss-server ~]# let "a=4*9"
[root@ss-server ~]# echo $a
36
[root@ss-server ~]# let a="3+5"
[root@ss-server ~]# echo $a
8 [root@ss-server ~]# a=10
[root@ss-server ~]# let a++ #表示变量a数值加1
[root@ss-server ~]# echo $a
11
{ } 大括号
这种大括号的组合,常用在字串的组合上,来看个例子
[root@ss-server ~]# mkdir aa{1,2,3}
[root@ss-server ~]# ls
aa1 aa2 aa3
[root@ss-server ~]# ll -d bb1*
drwxr-xr-x 2 root root 4096 Dec 5 11:37 bb1-k01
drwxr-xr-x 2 root root 4096 Dec 5 11:37 bb1-k02
drwxr-xr-x 2 root root 4096 Dec 5 11:37 bb1-k03
[root@ss-server ~]# ll -d cc1*
drwxr-xr-x 2 root root 4096 Dec 5 11:37 cc1-k01
drwxr-xr-x 2 root root 4096 Dec 5 11:37 cc1-k02
drwxr-xr-x 2 root root 4096 Dec 5 11:37 cc1-k03
[root@ss-server ~]# ll -d dd1*
drwxr-xr-x 2 root root 4096 Dec 5 11:37 dd1-k01
drwxr-xr-x 2 root root 4096 Dec 5 11:37 dd1-k02
drwxr-xr-x 2 root root 4096 Dec 5 11:37 dd1-k03
[root@ss-server ~]# touch {wan,han}_{1,2,3}
[root@ss-server ~]# ls wan*
wan_1 wan_2 wan_3
[root@ss-server ~]# ls han*
han_1 han_2 han_3
[root@ss-server ~]# chmod 755 /root/wan_{1,2,3}
[root@ss-server ~]# ll /root/wan_{1,2,3}
-rwxr-xr-x 1 root root 0 Dec 5 11:39 /root/wan_1
-rwxr-xr-x 1 root root 0 Dec 5 11:39 /root/wan_2
-rwxr-xr-x 1 root root 0 Dec 5 11:39 /root/wan_3
这组符号在适用性上相当广泛。能加以善用的话,回报是精简与效率。像下面的例子
?表示任意单个字符!!!
[root@ss-server ~]# chown app.app /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
如果不是因为支援这种用法,我们得写几行重复几次呀!
[ ] 中括号
常出现在流程控制中,扮演括住判断式的作用。
[root@ss-server ~]# ls hahaha
ls: cannot access hahaha: No such file or directory
[root@ss-server ~]# echo $?
2 [root@ss-server ~]# cat a.sh
#!/bin/bash ls hahaha >/dev/null 2>&1
if [ "$?" != 0 ];then
echo "Executes error"
exit 1
fi [root@ss-server ~]# sh a.sh
Executes error
这个符号在正则表达式中担任类似 "范围" 或 "集合" 的角色
[root@ss-server ~]# touch aaa{1,2,3,4}
[root@ss-server ~]# ls aaa*
aaa1 aaa2 aaa3 aaa4
[root@ss-server ~]# rm -f aaa[1234]
[root@ss-server ~]# ls aaa*
ls: cannot access aaa*: No such file or directory 注意:
rm -f aaa[1234] 表示删除aaa1、aaa2、aaa3、aaa4
相当于
rm -f aaa{1,2,3,4} 注意:
只有在删除文件的时候,[]可以起到上面类似 "范围" 或 "集合" 的角色!
在其他操作都不会起到该作用! 如下,在touch的时候,[]并没有起到范围或集合的作用!
[root@ss-server ~]# touch aa[123]
[root@ss-server ~]# touch aa[123]_[xyz]
[root@ss-server ~]# ls aa*
aa[123] aa[123]_[xyz]
[[ ]]
这组符号与先前的 [] 符号,基本上作用相同,但它允许在其中直接使用 || 与&& 逻辑等符号。||表示"或",&&表示"和" 。双中括号[[]]和单中括号[]的区别,在下面会详细提到。
[root@ss-server ~]# cat a.sh
#!/bin/bash
read -p "请输入一个数字: " num
if [[ ${num} > 10 && ${num}< 30 ]];then
echo "你输入的数字是${num}"
else
echo "输入的数字不符合要求"
fi [root@ss-server ~]# sh a.sh
请输入一个数字: 16
你输入的数字是16
[root@ss-server ~]# sh a.sh
请输入一个数字: 56
输入的数字不符合要求 上面脚本还可以改写为下面内容,效果是一样的!
[root@ss-server ~]# cat a.sh
#!/bin/bash #echo -n表示不换行
echo -n "输入一个数字: "
read num
if [[ ${num} > 10 && ${num}< 30 ]];then
echo "你输入的数字是${num}"
else
echo "输入的数字不符合要求"
fi [root@ss-server ~]# sh a.sh
输入一个数字: 19
你输入的数字是19
[root@ss-server ~]# sh a.sh
输入一个数字: 48
输入的数字不符合要求 ===============================================
需要注意:
if判断语句中如果使用[[]],可以在[[]]中直接使用&&、||符号,表示"和"、"或"。可以用于字符串对比符号,也可以用于整数对比符号。
if判断语句中如果使用[],在[]中可以使用-a、-o,表示"和"、"或",但是这个用于整数比较时只能使用"-eq、-ne、-ge、-gt、-lt、-le",不能使用>、>=、<、<=、=、!=。 [root@ss-server ~]# cat a.sh
#!/bin/bash
read -p "请输入一个数字: " num
if [ ${num} -gt 10 -a ${num} -le 30 ];then
echo "你输入的数字是${num}"
else
echo "输入的数字不符合要求"
fi [root@ss-server ~]# sh a.sh
请输入一个数字: 12
你输入的数字是12
[root@ss-server ~]# sh a.sh
请输入一个数字: 45
输入的数字不符合要求 上面脚本中的[ ${num} -gt 10 -a ${num} -le 30 ]
不能改为:
[ ${num} -ge 10 ] -a [${num} -le 30 ]
也不能改为
[ ${num} > 10 -a ${num} < 30 ] [[]]的&&、||也可以用于整数对比。
[root@ss-server ~]# cat a.sh
#!/bin/bash
read -p "请输入一个数字: " num
if [[ ${num} -ge 10 && ${num} -le 30 ]];then
echo "你输入的数字是${num}"
else
echo "输入的数字不符合要求"
fi
[root@ss-server ~]# sh a.sh
请输入一个数字: 17
你输入的数字是17
[root@ss-server ~]# sh a.sh
请输入一个数字: 67
输入的数字不符合要求
|| 逻辑符号
这个会时常看到,代表 or 逻辑的符号,表示前一个命令执行成功,则就此结束,后一个命令就不执行;前一个命令执行失败,后一个命令才会执行。如 A || B 表示A执行成功后,B就不会再执行了;A执行失败或不执行,B才能执行。
&& 逻辑符号
这个也会常看到,代表 and 逻辑的符号,表示串行,即前一个命令执行成功,后一个命令才接着执行;前一个命令执行失败,则就此结束,后一个命令也不会执行。如 A && B 表示A执行成功后,B也会跟着执行了;A执行失败或不执行,B也不会执行了。
& 后台工作
单一个& 符号,且放在完整指令列的最后端,即表示将该指令列放入后台中工作。 放在几个指令中间时,表示并行,实质就是在后台并行执行,跟指令前后顺序无关。
[root@ss-server ~]# tar -zvcf test1.tar.gz test1 > /dev/null &
\<...\> 单字边界
这组符号在规则表达式中,被定义为\"边界\"的意思。如下想要在test文件中找寻 the 这个单字时,如果我们用
[root@ss-server ~]# cat test
the
there
this is a
123456
thee
[root@ss-server ~]# grep "the" test
the
there
thee
如上会发现,像 there、thee这类的单字,也会被当成是匹配的单字。因为 the 正巧是there、thee的一部份。如果要想必免这种情况,就得加上单字边界符号,进行精准匹配:
[root@ss-server ~]# cat test
the
there
this is a
123456
thee
[root@ss-server ~]# grep "the" test
the
there
thee
[root@ss-server ~]# grep "\<the\>" test
the 另外:上面在进行grep精准匹配时,除了使用\<str\>单字边界符号,还可以使用grep -w进行精准匹配!
[root@ss-server ~]# cat test
the
there
this is a
123456
thee
[root@ss-server ~]# grep -w "the" test
the 可以参考:https://www.cnblogs.com/kevingrace/p/9299232.html
+ 加号
在运算式中,她用来表示 "加法"。
[root@ss-server ~]# expr 10 + 11 + 12
33 注意:expr命令中的计算符号和数字中间一定要有空格!!否则无效!并且后面的运算两边不能有引号,否则也无效! 下面都是错误的!!
[root@ss-server ~]# expr 10+11+12
10+11+12
[root@ss-server ~]# expr "10 + 11 + 12"
10 + 11 + 12 另外:注意expr使用*乘法的时候,需要在*前面加上转义符号\,否则无效!
[root@ss-server ~]# expr 2 * 3
expr: syntax error
[root@ss-server ~]# expr 2 \* 3
6
此外在正则表达式中,用来表示"很多个"的前面字元的意思。但是注意,正则里使用+符号表示"很多个"意思时,+号前面必须加上\\符号!!
[root@ss-server ~]# cat test
123456
10aaaahuihhhhh
s34eddddd
kkkhuan
[root@ss-server ~]# grep "10\\+a" test
10aaaahuihhhhh
[root@ss-server ~]# grep "e\\+d" test
s34eddddd
[root@ss-server ~]# grep "\\k" test
kkkhuan
- 减号
在运算式中,她用来表示 "减法"。
[root@ss-server ~]# expr 10 - 2
8
在 cd 指令中则比较特别,"cd -"表示变更工作目录到\"上一次\"工作目录。
[root@ss-server ~]# cd /usr/local/src/
[root@bz3aomsmsap1002 src]# cd
[root@ss-server ~]# cd -
/usr/local/src
[root@bz3aomsmsap1002 src]#
% 除法后的余数
在运算式中,用来表示 "除法"后的余数。 [运算式中的乘法*,用的时候需要在前面加一个转移符 expr 5 \* 10]
[root@ss-server ~]# expr 10 % 2
0
[root@ss-server ~]# expr 10 % 3
1
[root@ss-server ~]# expr 10 % 6
4
[root@ss-server ~]# expr 6 % 9
6
[root@ss-server ~]# expr 6 % 90
6
[root@ss-server ~]# expr 5 % 6
5 %表示余数,即整除后的余数是多少。
如果小除大,则%余数统一为前面那个小的数。
此外,也被运用在关于变量的规则表达式当中的下列
${parameter%word}
${parameter%%word} 一个 % 表示最短的 word 匹配,两个表示最长的 word 匹配。
可以参考上面"参数替换"部分有详细介绍
= 等号
常在设定变数时看到的符号。
[root@ss-server ~]# vara="hello world"
[root@ss-server ~]# echo "vara=${vara}"
vara=hello world
或者像是 PATH 的设定,甚至应用在运算或判断式等此类用途上。
== 等号
常在条件判断式中看到,代表 "等于" 的意思。
if [ $vara == $varb ]
...下略
!= 不等于
常在条件判断式中看到,代表 "不等于" 的意思。
if [ $vara != $varb ]
...下略
^
这个符号在正则表达式中,代表行的 "开头" 位置!
输出/输入重导向
> 、>>、< 、<< 、<>、>&、>&2
文件描述符(File Descriptor),用一个数字(通常为0-9)来表示一个文件。
常用的文件描述符如下:
文件描述符 名称 常用缩写 默认值
0 标准输入 stdin 键盘
1 标准输出 stdout 屏幕
2 标准错误输出 stderr 屏幕
在简单地用<或>时,相当于使用 0< 或 1>。如下面说明:
# cmd > file
把cmd命令的输出重定向到文件file中。如果file已经存在,则清空原有文件,使用bash的noclobber选项可以防止复盖原有文件。[即>表示覆盖内容]
# cmd >> file
把cmd命令的输出重定向到文件file中,如果file已经存在,则把信息加在原有文件後面。 [即>>表示追加内容]
# cmd < file
使cmd命令从file读入
# cmd << text
从命令行读取输入,直到一个与text相同的行结束。除非使用引号把输入括起来,此模式将对输入内容进行shell变量替换。如果使用<<- ,则会忽略接下来输入行首的tab,结束行也可以是一堆tab再加上一个与text相同的内容,可以参考後面的例子。
# cmd <<< word
把word(而不是文件word)和後面的换行作为输入提供给cmd。
# cmd <> file
以读写模式把文件file重定向到输入,文件file不会被破坏。仅当应用程序利用了这一特性时,它才是有意义的。
# cmd >| file
功能同>,但即便在设置了noclobber时也会复盖file文件,注意用的是|而非一些书中说的!,目前仅在csh中仍沿用>!实现这一功能。
: > filename 把文件\"filename\"截断为0长度.# 如果文件不存在, 那么就创建一个0长度的文件(与'touch'的效果相同).
# cmd >&n 把输出送到文件描述符n
# cmd m>&n 把输出 到文件符m的信息重定向到文件描述符n
# cmd >&- 关闭标准输出
# cmd <&n 输入来自文件描述符n
# cmd m<&n m来自文件描述各个n
# cmd <&- 关闭标准输入
# cmd <&n- 移动输入文件描述符n而非复制它。(需要解释)
# cmd >&n- 移动输出文件描述符 n而非复制它。(需要解释)
注意: >&实际上复制了文件描述符,这使得cmd > file 2>&1与cmd 2>&1 >file的效果不一样。
关于EOF用法:https://www.cnblogs.com/kevingrace/p/6257490.html
通常在执行一个命令时,如果不想打印命令执行的结果(包括正确或错误的结果信息),则通常使用"command >/dev/null 2>&1"
Shell中几种特殊的参数变量的引用
$1、$2、$3……${10}、${11}、${12}…… :表示脚本传入的的各个参数,注意当需表示两位数以后的参数时数字要用花括号括起。
$@ 列出所有的参数,各参数用空格隔开
$* 列出所有的参数,各参数用环境变量的第一个字符隔开
$* 和 $@ 的区别
1)$* 将所有的引用变量视为一个整体。但$@则仍旧保留每个引用变量的区段观念。
2)当不加引号时,$*和$@二者都是返回传入的参数,但是当加了引号后,$*把参数作为一个字符串整体(单字符串)返回,$@把每个参数作为一个字符串返回!
1) 示例1
[root@ss-server ~]# cat a.sh
#!/bin/bash for i in $*
do
echo $i
done echo "++++++ \$*和\$@对比(不加双引号) ++++++" for j in $@
do
echo $j
done [root@ss-server ~]# sh a.sh aa bb cc
aa
bb
cc
++++++ $*和$@对比(不加双引号) ++++++
aa
bb
cc 2) 示例2
[root@ss-server ~]# cat a.sh
#!/bin/bash for i in "$*"
do
echo $i
done echo "++++++ \$*和\$@对比(加双引号) ++++++" for j in "$@"
do
echo $j
done
[root@ss-server ~]# sh a.sh aa bb cc
aa bb cc
++++++ $*和$@对比(加双引号) ++++++
aa
bb
cc 3)示例3,在一个shell函数里分别定义 加双引号和不加双引号 传参时,$@和$*的区别
[root@ss-server ~]# cat a.sh
#! /bin/bash function test() {
echo "未加引号,二者相同"
echo $*
echo $@
echo "加入引号后对比" echo "----"\$*----""
for N in "$*"
do
echo $N
done echo "----"\$@----""
for N in "$@"
do
echo $N
done
}
test 11 22 33
[root@ss-server ~]# sh a.sh
未加引号,二者相同
11 22 33
11 22 33
加入引号后对比
----$*----
11 22 33
----$@----
11
22
33 ====================================================================================
通过上面对比,可以发现:
不加引号时,$*和$@二者都是返回传入的参数;
加了引号后,$*把参数作为一个字符串整体(单字符串)返回,$@把每个参数作为一个字符串返回!
命令列表
and列表 statement1 && statement2 && ..... 表示只有在前面所有的命令都执行成功的情况下才执行后一条命令;即前面成功,后面继续执行;前面失败,后面也不执行!
or列表 statement1 || statement2 || ….. 表示允许执行一系列命令直到有一条命令成功为止,其后所有命令将不再被执行;即前面成功,后面不执行;前面失败,后面执行!!
[root@ss-server ~]# cat a.sh
#!/bin/bash touch file_one >/dev/null 2>&1
rm -f file_two >/dev/null 2>&1 if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo " there";then
echo "in if"
else
echo "in else"
fi
exit 0
[root@ss-server ~]# sh a.sh
hello
in else
if逻辑判断语句中常用到的参数 以及 注意细节 (如[[]]和[]的区别)
[ -a file ] 如果 file 存在则为真。
[ -e file ] 如果 file 存在则为真。 [ -f file ] 如果 file 存在且是一个普通文件则为真。
[ -d file ] 如果 file 存在且是一个目录则为真。 [ -b file ] 如果 file 存在且是一个块特殊文件则为真。(即设备文件,如/dev/sda1、/dev/sda2) [ -h file ] 如果 file 存在且是一个符号文件则为真。(符号文件即是软链接文件)
[ -L file ] 如果 file 存在且是一个符号文件则为真。(符号文件即是软链接文件) [ -g file ] 如果 file 存在且已经设置了SGID则为真。
[ -u file ] 如果 file 存在且设置了SUID则为真。
[ -k file ] 如果 file 存在且已经设置了粘制位则为真。(即设置了t权限的目录,粘制位仅对目录有效) [ -r file ] 如果 file 存在且是可读的则为真。
[ -w file ] 如果 file 存在且是可写的则为真。
[ -x file ] 如果 file 存在且是可执行的则为真。 [ -s file ] 如果 file 存在且大小不为0则为真。 [ -O file ] 如果 file 存在且属有效用户ID则为真。
[ -G file ] 如果 file 存在且属有效用户组则为真。 [ file1 -nt file2 ] 如果 file1 比 file2 要老(即先创建), 或者 file1 存在且 file2不存在则为真。
[ file1 -ot file2 ] 如果 file1 比 file2 要老(即先创建), 或者 file2 存在且 file1 不存在则为真。 [ -z str ] 如果str字符串的长度为零则为真。 (即空串为真)
[ -n str ] or [ str ] 如果str字符串的长度为非零则为真。 (即非空串为真) [ str1 == str2 ] 如果2个字符串相同则为真。
[ str1 != str2 ] 如果字符串不相等则为真。 二、简单总结
===========================================================================
1)字符串判断
str1 = str2 当两个串有相同内容、长度时为真
str1 != str2 当串str1和str2不等时为真
-n str1 当串的长度大于0时为真(串非空)
-z str1 当串的长度为0时为真(空串)
str1 当串str1为非空时为真。等于"-n star1" 2)数字的判断
int1 -eq int2 两数相等为真
int1 -ne int2 两数不等为真
int1 -gt int2 int1大于int2为真
int1 -ge int2 int1大于等于int2为真
int1 -lt int2 int1小于int2为真
int1 -le int2 int1小于等于int2为真 3)文件的判断
-a file 文件存在为真
-z file 文件存在为真
-r file 用户可读为真
-w file 用户可写为真
-x file 用户可执行为真
-f file 文件为普通文件为真
-d file 文件为目录为真
-s file 文件大小非0时为真
-h file 文件为符号文件为真
-L file 文件为符号文件为真
-g file 文件为SGID权限文件为真
-u file 文件为SUID权限文件为真
-k file 文件为T权限文件为真 4)复杂逻辑判断
-a 与
-o 或
! 非 三、注意细节
===========================================================================
1)在if的中括号中,判断变量的值,加不加双引号的问题?
-z 判断变量的值,是否为空:
变量的值,为空,返回0,为true
变量的值,非空,返回1,为false
-n 判断变量的值,是否为空:
变量的值,为空,返回1,为false
变量的值,非空,返回0,为true
str="abc"
[ -z "$str" ] 单中括号,变量必须要加双引号!
[[ -z $str ]] 双中括号,变量不用加双引号 [ -n "$str" ] 单中括号,变量必须要加双引号!
[[ -n $str ]] 双中括号,变量不用加双引号 2)多个条件判断,[] 和 [[]] 的区别????????????????????
&& 并且,相当于and
|| 或,相当于or -a 并且,相当于and
-o 或者,相当于or --------------------------------------------
2.1)双中括号[[]]的条件判断
[[ ]] 双中括号的条件判断用"&&" 和 "||" || 满足一个条件满足就成立;或者的关系
[[ $a -lt 3 || $a -gt 6 ]]
[[ $a -lt 3 ]] || [[ $a -gt 6 ]] # 写在外面也可以 && 必须同时满足两个条件同时;并且的关系。
[[ $a -gt 3 && $a -lt 10 ]]
[[ $a -gt 3 ]] && [[$a -lt 10 ]] # 写在外面也可以 这里需要注意的问题的是:
[[]]双中括号的判断语句中,只能使用&&和||,可以在[[]]内部使用,也可以在[[]]外面使用!
[[]]双中括号的判断语句中不能使用-a和-o参数!!!!!! 如果使用下面写法就是错误的!!!!!!
[[ $a -lt 3 -o $a -gt 6 ]]
[[ $a -lt 3 ]] -o [[ $a -gt 6 ]]
[[ $a -gt 3 -a $a -lt 10 ]]
[[ $a -gt 3 ]] -a [[$a -lt 10 ]] --------------------------------------------
2.2)单中括号[]的条件判断
[ ] 单中括号的条件判断可以使用-a和-o的参数,但是必须在单[ ]中括号内判断条件!!不能在单中括号外面!!
[ $a -lt 10 -o $a -gt 20 ] 这个"或者"条件成立
[ $a -lt 10 ] -o [ $a -gt 20 ] 这个"或者"不成立,因为必须在中括号内判断!!!! 如果想在[]中括号外判断两个条件,必须用&& 和 || 比较!
[ $a -lt 10 ] || [ $a -gt 20 ] 这个"或者"条件成立
[ $a -lt 10 ] && [ $a -gt 20 ] 这个"并且"条件成立 同样需要注意:|| 和 && 不能在单中括号[]内使用,只能在单中括号[]外面使用!!! 3) 当判断某个变量的值是否满足正则表达式的时候,必须使用[[ ]] 双中括号!!!!
示例:
[root@ss-server ~]# str=13611082178
[root@ss-server ~]# [[ ${str} =~ [0-9]{11} ]]
[root@ss-server ~]# echo $?
0 如果使用单中括号,会直接报错:
[root@ss-server ~]# str=13611082178
[root@ss-server ~]# [ ${str} =~ [0-9]{11} ]
-bash: [: =~: binary operator expected
shell脚本获取第10个参数 在Shell脚本中,可以用$n的方式获取第n个参数
[root@ansible-server ~]# cat a.sh
#!/bin/bash
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} [root@ansible-server ~]# sh a.sh a b c d 1 2 3 4 8 ab
a b c d 1 2 3 4 8 ab 取第10个参数, 要用${10}, 不能使用$10(这个表示第1个参数加上0)。因为个位数的参数,可以直接使用数字。但两位以上数字的参数,必须使用{}符号!!!!
#!/bin/bash
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 [root@ansible-server ~]# sh a.sh a b c d 1 2 3 4 8 ab
a b c d 1 2 3 4 8 a0 即上面脚本中$10 取的值为$1+0 再看几个例子
[root@ansible-server ~]# cat a.sh
#!/bin/bash
#echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10
echo $3 $12 [root@ansible-server ~]# sh a.sh a b c d 1 2 3 4 8 ab
c a2 [root@ansible-server ~]# cat a.sh
#!/bin/bash
#echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10
echo $3 ${12} [root@ansible-server ~]# sh a.sh a b c d 1 2 3 4 8 ab bo kevin
c kevin
$# 是传递给脚本的参数个数;
$0 是脚本本身的名字;
$1 是传递给该shell脚本的第一个参数;
$2 是传递给该shell脚本的第二个参数;
$@ 是传递给脚本的所有参数的列表(是多个字符串,每个参数为1个字符串);
$* 是传递给脚本的所有参数的列表(以一个单字符串显示所有参数),与位置变量不同,参数可超过9个;
$$ 是运行脚本的当前进程ID号;
$? 是显示执行上一条Shell命令的返回值,0表示没有错误,其他表示有错误。
如下,用一个简单的脚本来说明上面这些变量的含义
[root@kevin ~]# vim /root/path.sh
#!/bin/sh
echo "the number of parameters passed to the script: $#"
echo "the name of the script itself: $0"
echo "the first parameter passed to the shell script: $1"
echo "the second parameter passed to the shell script: $2"
echo "the list of all the parameters passed to the script(some string): $@"
echo "the list of all the parameters passed to the script(one string): $*"
echo "the current process ID number of the script which is running: $$"
echo "the return value of the last shell command performed: $?" [root@kevin ~]# chmod 755 /root/path.sh
[root@kevin ~]# ll /root/path.sh
-rwxr-xr-x. 1 root root 512 Jun 25 11:21 /root/path.sh [root@kevin ~]# sh /root/path.sh 10 20 30
the number of parameters passed to the script: 3
the name of the script itself: /root/path.sh
the first parameter passed to the shell script: 10
the second parameter passed to the shell script: 20
the list of all the parameters passed to the script(some string): 10 20 30
the list of all the parameters passed to the script(one string): 10 20 30
the current process ID number of the script which is running: 372
the return value of the last shell command performed: 0
Shell脚本常用命令 -exit 和 if
1、exit
exit 0 退出shell,成功
exit 1 退出shell,失败
exit 2 退出shell,用法不当 需要注意:
如果shell脚本中调用的子脚本的exit,那么会退出子脚本
如果是source一个子脚本,里面的exit会导致外面的脚本也退出 ==============================================================
2、if
1) if [-z "$name"]
判断name是否为空字符串,如果空,则为真,执行if的内容
等同于 if ["$name" = ""]
等同于[! "$name"] 2) if的几个参数
-z 字符串是否为空,空为真
-n 指定字符串是否不空,不空为真
-a 某东西不存在,则为真。不限定为字符串
-f 普通文件是否存在
-d 目录是否存在
-e 某东西是否存在,不限定为文件
Shell脚本中判断参数是否为空,如果为空就停止后续操作
注意下面的方法
if [ str1 = str2 ] 当两个串有相同内容、长度时为真
if [ str1 != str2 ] 当串str1和str2不等时为真
if [ -n str1 ] 当串的长度大于0时为真(串非空) 。 注意: 这个等同于if [ ! -n str1 ] ,前提是里面的str1不加上"",如果加上""就等同于if [ -z str1 ]了!
if [ -z str1 ] 当串的长度为0时为真(空串) 。 注意:这个等同于 if [ ! -n "str1" ],前提是str1必须要加上""双引号!! ==================================================================
[root@bz3aomsmsap1002 mnt]# cat test.sh
#!/bin/bash
AN=""
BN="sadf"
if [ -z ${AN} ];then
echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
exit 1
fi echo "结果为:${AN} is a good ${BN}" [root@bz3aomsmsap1002 mnt]# sh test.sh
没有变量AN,无法执行后续操作,请确认输入了AN参数 -----------------------------------------
[root@bz3aomsmsap1002 mnt]# cat test.sh
#!/bin/bash
AN="ha"
BN="sadf"
if [ -z ${AN} ];then
echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
exit 1
fi echo "结果为:${AN} is a good ${BN}" [root@bz3aomsmsap1002 mnt]# sh test.sh
结果为:ha is a good sadf ==================================================================
如果要想使用-n代替-z,则做法如下:
必须注意:
下面的if判断语句中的-n后面的变量必须要加上双引号""!否则就失效!
因为如果不加""的话,就等同于了效于if [ -n ]
[root@bz3aomsmsap1002 mnt]# cat test.sh
#!/bin/bash
AN=""
BN="sadf"
if [ ! -n "${AN}" ];then
echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
exit 1
fi echo "结果为:${AN} is a good ${BN}" [root@bz3aomsmsap1002 mnt]# sh test.sh
没有变量AN,无法执行后续操作,请确认输入了AN参数 -----------------------------------------
[root@bz3aomsmsap1002 mnt]# cat test.sh
#!/bin/bash
AN="ru"
BN="sadf"
if [ ! -n "${AN}" ];then
echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
exit 1
fi echo "结果为:${AN} is a good ${BN}" [root@bz3aomsmsap1002 mnt]# sh test.sh
结果为:ru is a good sadf -----------------------------------------
如果不加双引号,则if [ ! -n ] 就等同于了 -f [ -n ] [root@bz3aomsmsap1002 mnt]# cat test.sh
#!/bin/bash
AN=""
BN="sadf"
if [ ! -n ${AN} ];then
echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
exit 1
fi echo "结果为:${AN} is a good ${BN}" [root@bz3aomsmsap1002 mnt]# sh test.sh
结果为: is a good sadf -----------------------------------------
[root@bz3aomsmsap1002 mnt]# cat test.sh
#!/bin/bash
AN="ru"
BN="sadf"
if [ ! -n ${AN} ];then
echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
exit 1
fi echo "结果为:${AN} is a good ${BN}" [root@bz3aomsmsap1002 mnt]# sh test.sh
结果为:ru is a good sadf
$(( ))、$( )、${ }的区别
===================================================================
一、$( ) 与 ` ` (反引号)
在bash shell中,$( ) 与 ` `(反引号) 都是用来做命令替换用(command substitution)的。
[root@bobo tmp]# echo `hostname`
kevin-testserver
[root@bobo tmp]# echo $(hostname)
kevin-testserver 比如查看上一星期天的日期
[root@bobo tmp]# echo the last sunday is $(date -d "last sunday" +%Y-%m-%d)[/code]
the last sunday is 2019-10-27[/code] ===================================================================
二、${ } 用来作变量替换。
一般情况下,$var 与 ${var} 并没有什么不一样。但是用${ }会比较精确的界定变量名称的范围。
例如下面的例子,原本是打算先将$A的结果替换出来,然后再补一个B字母于其后。
如果使用$AB打印结果就为空,但是使用${A}B打印就不一样了。
[root@bobo tmp]# A=B
[root@bobo tmp]# echo $AB [root@bobo tmp]# echo ${A}B
BB
[root@bobo tmp]# 在bash中。${ }功能是十分强大的,不仅仅是用来界定变量名称,
--------------------------------------
1)${}可以灵活地用来截图变量中的字符串
具体可以参考:https://www.cnblogs.com/kevingrace/p/8868262.html 例如:var="http://www.kevin.com/shibo/anhuigrace"
我们可以用 ${ } 分别替换获得不同的值:
${var#*/}:拿掉第一条/及其左边的字符串:/www.kevin.com/shibo/anhuigrace
${var##*/}:拿掉最后一条/及其左边的字符串:anhuigrace
${var#*.}:拿掉第一个.及其左边的字符串:kevin.com/shibo/anhuigrace
${var##*.}:拿掉最后一个.及其左边的字符串:com/shibo/anhuigrace
${var%/*}:拿掉最后一条/及其右边的字符串:http://www.kevin.com/shibo
${var%%/*}:拿掉第一条/及其右边的字符串:http:
${var%.*}:拿掉最后一个.及其右边的字符串:http://www.kevin
${var%%.*}:拿掉第一个.及其右边的字符串:http://www 记忆的方法为:
# 是去掉左边(在键盘上 # 在 $ 之左边)
% 是去掉右边(在键盘上 % 在 $ 之右边)
单一符号是最小匹配﹔
两个符号是最大匹配。 --------------------------------------
2)${}可以对变量值里的字符串作替换
${file/dir/path}:将第一个 dir提换为path:
${file//dir/path}:将全部dir提换为path: 示例:
[root@bobo tmp]# cat test.sh
#!/bin/bash var="/data/web/kevin/www/web/ui/web/list" echo "${var}"
echo "${var/web/shi}"
echo "${var//web/shi}"
[root@bobo tmp]# sh test.sh
/data/web/kevin/www/web/ui/web/list
/data/shi/kevin/www/web/ui/web/list
/data/shi/kevin/www/shi/ui/shi/list --------------------------------------
3) 利用 ${ } 还可针对不同的变量状态赋值(没设定、空值、非空值)
${var-kevin.txt}:假如$var没有设定,则使用kevin.txt作传回值。(空值及非空值时不作处理)
${var:-kevin.txt}:假如$var没有设定或为空值,则使用kevin.txt作传回值。(非空值时不作处理)
${var+kevin.txt}:假如$var设为空值或非空值,均使用kevin.txt作传回值。(没设定时不作处理)
${var:+kevin.txt}:若$var为非空值,则使用kevin.txt作传回值。(没设定及空值时不作处理)
${var=kevin.txt}:若$var没设定,则使用kevin.txt作传回值,同时将$var赋值为kevin.txt。(空值及非空值时不作处理)
${var:=kevin.txt}:若$var没设定或为空值,则使用kevin.txt作传回值,同时将$var赋值为kevin.txt。(非空值时不作处理)
${var?kevin.txt}:若$var没设定,则将kevin.txt输出至STDERR。(空值及非空值时不作处理)
${var:?kevin.txt}:若$var没设定或为空值,则将kevin.txt输出至STDERR。(非空值时不作处理) 示例:
[root@bobo tmp]# cat test.sh
#!/bin/bash #var="/data/web/kevin/www/web/ui/web/list" echo "${var}"
echo "${var-my.txt}"
echo "${var:-my.txt}"
echo "${var+my.txt}"
echo "${var:+my.txt}"
echo "${var=my.txt}"
echo "${var:=my.txt}"
echo "${var?my.txt}"
echo "${var:?my.txt}" [root@bobo tmp]# sh test.sh my.txt
my.txt my.txt
my.txt
my.txt
my.txt 修改下脚本
[root@bobo tmp]# cat test.sh
#!/bin/bash var="/data/web/kevin/www/web/ui/web/list" echo "${var}"
echo "${var-my.txt}"
echo "${var:-my.txt}"
echo "${var+my.txt}"
echo "${var:+my.txt}"
echo "${var=my.txt}"
echo "${var:=my.txt}"
echo "${var?my.txt}"
echo "${var:?my.txt}" [root@bobo tmp]# sh test.sh
/data/web/kevin/www/web/ui/web/list
/data/web/kevin/www/web/ui/web/list
/data/web/kevin/www/web/ui/web/list
my.txt
my.txt
/data/web/kevin/www/web/ui/web/list
/data/web/kevin/www/web/ui/web/list
/data/web/kevin/www/web/ui/web/list
/data/web/kevin/www/web/ui/web/list 需要注意的是:
以上理解一定要分清楚unset 与 null 及 non-null 这三种赋值状态。一般而言:
: 与 null 有关;
若不带 : 的话, 则 null 不受影响,;
若带 : 的话,则连 null 也受影响. --------------------------------------
4)${#var} 可计算出变量值的长度
[root@bobo tmp]# cat test.sh
#!/bin/bash var="/data/web/kevin/www/web/ui/web/list" echo "${#var}" [root@bobo tmp]# sh test.sh
35 这里就引申出shell中的数组的概念了,数组的使用可以参考:https://www.cnblogs.com/kevingrace/p/5761975.html 这里简单说明下:
一般而言,var="haha hehe heihei houhou" 这样的变量只是将${var}替换为一个单一的字符串,
[root@bobo tmp]# var="haha hehe heihei houhou"
You have mail in /var/spool/mail/root
[root@bobo tmp]# echo ${var}
haha hehe heihei houhou 如果改为 var=(haha hehe heihei houhou) ,则是将${var}定义为组数。
[root@bobo tmp]# var=(haha hehe heihei houhou) bash 的组数替换方法可参考如下方法:
${var[@]} 或 ${var[*]} 可得到 haha hehe heihei houhou (全部组数)
${var[0]} 可得到 haha (第一个组数),${var[1]} 则为第二个组数…
${#var[@]} 或 ${#var[*]} 可得到 4 (全部组数数量)
${#var[0]} 可得到4(即第一个组数(haha)的长度),${#var[3]} 可得到6(第四个组数(houhou)的长度)
var[3]=xyz 则是将第四个组数重新定义为xyz … [root@bobo tmp]# echo ${var[@]}
haha hehe heihei houhou
[root@bobo tmp]# echo ${var[*]}
haha hehe heihei houhou
[root@bobo tmp]# echo ${var[0]}
haha
[root@bobo tmp]# echo ${var[1]}
hehe
[root@bobo tmp]# echo ${#var[@]}
4
[root@bobo tmp]# echo ${#var[*]}
4
[root@bobo tmp]# echo ${#var[0]}
4
[root@bobo tmp]# echo ${#var[3]}
6
[root@bobo tmp]# var[3]=xyz
[root@bobo tmp]# echo ${var[@]}
haha hehe heihei xyz ===================================================================
三、 $(( )) 的用途:
1)$(( ))是用来作整数运算的。
+ - * / :分别为 "加、减、乘、除"。
% :余数运算
& | ^ !:分别为 "AND、OR、XOR、NOT" 运算。 [root@bobo tmp]# a=5; b=7; c=2
[root@bobo tmp]# echo $(( a+b*c ))
19
[root@bobo tmp]# echo $(( (a+b)/c ))
6
[root@bobo tmp]# echo $(( (a*b)%c))
1 在 $(( )) 中的变量名称,可于其前面加 $ 符号来替换,也可以不用,如:
[root@bobo tmp]# echo $(( $a + $b * $c))
19
[root@bobo tmp]# echo $(( ($a * $b) % $c))
1
Shell 脚本中诸如查看目录大小并排序等技巧
=====================================================================
查看目录下的文件大小并排序 1. 查看/data目录下空间大小排在前10位的文件
# du -sh /data/* | sort -nr | head -10 查看目录下所有文件的大小并按照大小排序
# du -sh * | sort -rh 2. 查看/data目录下空间大小排在前10位的目录(单位为G),并且只是在/data当前目录下查看,不轮询(用到参数"-maxdepth 1")
# find /data/* -maxdepth 1 -type d -exec /usr/bin/du -sh {} \;|grep '[0-9]G'|sort -rh|head -5 [bxapp@bz6aomdepap1001 ~]$ find /data/ftp/ONLINE/* -maxdepth 1 -type d -exec /usr/bin/du -sh {} \;|grep '[0-9]G'|sort -rh|head -5
64G /data/ftp/ONLINE/CCS
13G /data/ftp/ONLINE/MPB
11G /data/ftp/ONLINE/ICS
9.5G /data/ftp/ONLINE/mysql
9.0G /data/ftp/ONLINE/EOB =====================================================================
Shell中求字符串中单词的个数的几种方法 方法一:
[root@VM_16_9_centos tmp]# echo 'wang shi kevin ruo bao' | wc -w
5 方法二:
[root@VM_16_9_centos tmp]# echo 'wang shi kevin ruo bao' | awk '{print NF}'
5 方法三:
[root@VM_16_9_centos tmp]# s='wang shi kevin ruo bao'
[root@VM_16_9_centos tmp]# set ${s}
[root@VM_16_9_centos tmp]# echo $#
5 方法四:
[root@VM_16_9_centos tmp]# s='wang shi kevin ruo bao'
[root@VM_16_9_centos tmp]# a=($s)
[root@VM_16_9_centos tmp]# echo ${#a[@]}
5 方法五:
[root@VM_16_9_centos tmp]# s='wang shi kevin ruo bao'
[root@VM_16_9_centos tmp]# echo $s | tr ' ' '\n' | wc -l
5 =====================================================================
linux 中wc 用法小结
wc命令用于统计给定文件中的字节数、字数、行数。
如果没有给出文件名,则从标准输入读取。
wc同时也给出所有指定文件的总统计数。字是由空格字符区分开的最大字符串。 wc命令各选项含义如下:
- c 统计字节数
- l 统计行数
- w 统计字数 1. 统计行数:
# wc -l file 2. 如果需要将stdin作为输入,使用下列命令:
#cat file | wc -l 3. 统计单词数:
# wc -w file
# cat file | wc -w 4. 统计字符数:
# wc -c file
# cat file | wc -c 可以按照下面的方法统计文本中的字符数:
-n用于避免echo添加额外的换行符。
[root@VM_16_9_centos tmp]# echo "CCS"|wc -c
4
[root@VM_16_9_centos tmp]# echo -n "CCS"|wc -c
3
4 5. 当不使用任何选项执行wc时:
# wc file
1435 15763 112200
它会分别打印出文件的行数、单词数和字符数。 6. 使用-L选项打印出文件中最长一行的长度:
# wc file -L
205 =====================================================================
shell求两个数相除后的百分比 [root@VM_16_9_centos tmp]#
[root@VM_16_9_centos tmp]# cat test.sh
#!/bin/bash
NUM1=78
NUM2=345 Percent_1=$(printf "%d%%" $((${NUM1}*100/${NUM2})))
#或者 #保留1位小数,四舍五入
Percent_2=`awk 'BEGIN{printf "%.1f%%\n",('${NUM1}'/'${NUM2}')*100}'` #保留3位小数,四舍五入
Percent_3=`awk 'BEGIN{printf "%.3f%%\n",('${NUM1}'/'${NUM2}')*100}'` echo $Percent_1
echo $Percent_2
echo $Percent_3
[root@VM_16_9_centos tmp]# sh test.sh
22%
22.6%
22.609%