shell脚本之特殊符号总结性梳理
# 井号
- 这几乎是个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%
shell脚本之特殊符号总结性梳理的更多相关文章
- 【转】70个经典的 Shell 脚本面试问题
我们为你的面试准备选择了 70 个你可能遇到的 shell 脚面问题及解答.了解脚本或至少知道基础知识对系统管理员来说至关重要,它也有助于你在工作环境中自动完成很多任务.在过去的几年里,我们注意到所有 ...
- Shell 脚本面试问题大全
我们为你的面试准备选择了 70 个你可能遇到的 shell 脚本面试问题及解答.了解脚本或至少知道基础知识对系统管理员来说至关重要,它也有助于你在工作环境中自动完成很多任务.在过去的几年里,我们注意到 ...
- 70个经典的 Shell 脚本面试问题
转载自:http://www.imooc.com/article/1131 1) 如何向脚本传递参数 ? ./script argument 例子: 显示文件名称脚本 ./show.sh file1. ...
- Linux shell脚本学习(一)
一.shell脚本简介 shell脚本是用shell脚本语法将shell命令组织起来形成的文件形式.Shell脚本与Windows/Dos 下的批处理相似,主要为了将大量命令通过一个纯文本文件一次执行 ...
- Linux Shell编程第1章——Shell脚本编程概述
目录 Linux和Shell简介 Linux是一套可免费使用和自由传播的类UNIX操作系统.Shell是一种具备特殊功能的程序,它提供了用户与内核进行交互操作的一种接口.它接收用户输入的命令,并把它送 ...
- linux之shell脚本
1) 如何向脚本传递参数 ? ./script argument 例子: 显示文件名称脚本 ? 1 2 3 4 ./show.sh file1.txt cat show.sh #!/bin/bash ...
- shell 脚本关键字&符号
shell概念 "shell"既是一种解释型编程语言,也是一个这种编程语言的解释器的名字 shell是解释型语言,就是解释器会一条一条的翻译每一条语句并执行,对比之下,C语言是编译 ...
- shell脚本中的特殊符号
1.{} 大括号:用法一:通配符扩展eg: ls my_{finger,toe}s这条命令相当于如下命令的组合:ls my_fingers my_toeseg: mkdir {userA,userB, ...
- shell脚本中一些特殊符号
在shell中常用的特殊符号罗列如下: # ; ;; . , / \\ 'string'| ! $ ${} $? $$ $* \"string\"* ** ...
随机推荐
- java调用python的惨痛史(无法获取环境变量)
环境:java,was,python2.6,红帽linux,oracle,python用cx_Oracle 事情是这样的,有个需求,需要对数据库进行处理,简单说就是把数据取出来,用pyt ...
- January 16th, 2018 Week 03rd Tuesday
Accept who you are, and revel in it. 接受真实的自己并乐在其中. Try to accept youself and try to love yourself mo ...
- npm包开发(whale-makelink)
whale-makelink是一个npm工具,是强业务的工具,可以将当前工程目录下的项目文件夹,在README中生成项目的链接地址.Demo. 一.npm init 使用npm init生成packa ...
- Jquery 中 ajaxSubmit使用讲解
最近在使用ajaxForm,随便把使用方法记下下来,以便以后回顾. 1 ,引入依赖脚本 <script type="text/javascript" src="/j ...
- 【BZOJ4259】残缺的字符串
[BZOJ4259]残缺的字符串 Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时, ...
- 【九校3D2T3】世界第一的猛汉王
[问题描述] 卡普地公司举办了「世界第一的猛汉王」全球大会,来自世界各地的猛汉为了争夺「猛汉王」的名号前来一决高下.现在举行的是弓箭组选拔赛.卡普地公司为比赛新建了一张PVP地图——「猛汉竞技场」.有 ...
- Django之Form进阶
s6day76 内容回顾: Form组件: - 类 继承Form - 字段 字段 - 实例化 - is_valid() - cleaned_data - errors Form 组件: ...
- sed命令替换字符包含斜杠\,引号的处理方法
在字符替换中,可能会遇见引号,“/”等的替换,这时应该注意,sed的命令原型是: sed -i "s/oldstring/goalstring/g" file 如果一个路径是da ...
- QT插件+ROS 3 导入现有ROS包
http://blog.csdn.net/u013453604/article/details/52167213#t5
- python开发技巧---列表、字典、集合值的过滤
主要学习列表,字典,集合表达式的应用: 列表的解析式: 生成一个随机列表: In [4]: datalist = [randint(-10,10) for _ in range(10)] In [5] ...