#    井号

  1. 这几乎是个shell满场都有的符号,用在shell脚本的开头,如"#!/bin/bash"
  2.  
  3. 井号也常出现在一行的开头,或者位于完整指令之后,这类情况表示符号后面的是注解文字,不会被执行。
  4. 由于这个特性,当临时不想执行某行指令时,只需在该行开头加上 # 就行了。这常用在撰写过程中。
  5. 如果被用在指令中,或者引号双引号括住的话,或者在倒斜线的后面,那他就变成一般符号,不具上述的特殊功能。

~    用户家目录
算是个常见的符号,代表使用者的 home 目录:cd ~;也可以直接在符号后加上某帐户的名称:cd ~user或者当成是路径的一部份:~/bin
~+ 当前的工作目录,这个符号代表当前的工作目录,她和内建指令 pwd的作用是相同的。

  1. [root@VM_16_9_centos ~]# pwd
  2. /root
  3. [root@VM_16_9_centos ~]# echo ~+/var/log
  4. /root/var/log

~- 上次的工作目录,这个符号代表上次的工作目录。

  1. [root@VM_16_9_centos ~]# pwd
  2. /root
  3. [root@VM_16_9_centos ~]# echo ~+/var/log
  4. /root/var/log
  5. [root@VM_16_9_centos ~]# echo ~-/etc/httpd/logs
  6. /root/test/etc/httpd/logs

;    分号
在 shell 中,担任"连续指令"功能的符号就是"分号"。譬如以下的例子:

  1. [root@VM_16_9_centos ~]# mkdir test;cd test;echo "safd" >test1;cat test1;pwd
  2. safd
  3. /root/test

;;    连续分号
专用在 case 的选项,担任 Terminator 的角色。

  1. [root@localhost ~]# cat a.sh
  2. #!/bin/bash
  3.  
  4. read -p "please write:" fop
  5.  
  6. case ${fop} in
  7. help)
  8. echo "Usage: Command -help -version filename";;
  9. version)
  10. echo "version 0.1" ;;
  11. esac
  12.  
  13. [root@localhost ~]# sh a.sh
  14. please write:help
  15. Usage: Command -help -version filename

.    点号 (dot,就是“点”)
在 shell 中,使用者应该都清楚,一个 dot 代表当前目录,两个 dot 代表上层目录。

  1. [root@ss-server ~]# cd /usr/local/src/
  2. [root@bz3aomsmsap1002 src]# cd ../
  3. [root@bz3aomsmsap1002 local]# pwd
  4. /usr/local
  5.  
  6. [root@ss-server ~]# cd /usr/local/src/
  7. [root@bz3aomsmsap1002 src]# cd ../../
  8. [root@bz3aomsmsap1002 usr]# pwd
  9. /usr

如果档案名以 dot 开头,该档案就属特殊档案,用 ls指令必须加-a 选项才会显示(即查看隐藏文件)。除此之外,在 regularexpression 中,一个 dot 代表匹配一个字元。

' '    单引号 (single quote)
被单引号用括住的内容,将被视为单一字串。在引号内的代表变数的$符号,没有作用,也就是说,他被视为一般符号处理,防止任何变量替换。

  1. [root@localhost ~]# heyyou=homeecho
  2. [root@localhost ~]# echo '$heyyou'
  3. $heyyou

" "    双引号 (double quote)
被双引号用括住的内容,将被视为单一字串。它防止通配符扩展,但允许变量扩展。这点与单引数的处理方式不同。

  1. [root@VM_16_9_centos ~]# heyyou=homeecho
  2. [root@VM_16_9_centos ~]# echo ${heyyou}
  3. homeecho
  4. [root@VM_16_9_centos ~]# echo '${heyyou}'
  5. ${heyyou}
  6. [root@VM_16_9_centos ~]# echo "${heyyou}"
  7. homeecho

``     倒引号,相当于$(),表示命令替换,将里面命令执行结果传给变量参数。
在前面的单双引号,括住的是字串,但如果该字串是一列命令列,会怎样?答案是不会执行。要处理这种情况,我们得用倒单引号``来做。

  1. [root@VM_16_9_centos ~]# fdv=`date +%F`
  2. [root@VM_16_9_centos ~]# echo "Today $fdv"
  3. Today 2019-11-28

在倒引号内的 date +%F 会被视为指令,执行的结果会带入 fdv 变数中。

,     逗点 (标点中的逗号)
这个符号常运用在运算当中当做"区隔"用途。如下例:

  1. [root@VM_16_9_centos ~]# cat a.sh
  2. #!/bin/bash
  3. let "t1 = ((a = 5 + 3, b = 7 - 1, c = 15 / 3))"
  4. echo "t1= $t1, a = $a, b = $b"
  5. [root@VM_16_9_centos ~]# sh a.sh
  6. t1= 5, a = 8, b = 6

/    斜线
在路径表示时,代表目录。

  1. [root@VM_16_9_centos ~]# cd /etc/rc.d
  2. [root@VM_16_9_centos rc.d]# cd ../..
  3. [root@VM_16_9_centos /]#

通常单一的 / 代表 root 根目录的意思;在四则运算中,代表除法的符号。

  1. [root@VM_16_9_centos ~]# let "num1 = ((a = 10 / 2, b = 25 / 5))"
  2. [root@VM_16_9_centos ~]# echo ${num1}
  3. 5

\\     双倒斜线 和 \ 单倒斜线

  1. \\ 双倒斜线:放在指令前,有取消 aliases的作用
  2. =======================================
  3. [root@localhost ~]# alias kevin="ls"
  4. [root@localhost ~]# kevin
  5. a anaconda-ks.cfg
  6. [root@localhost ~]# kevin -l
  7. total 4
  8. -rw-r--r-- 1 root root 0 Nov 28 22:56 a
  9. -rw-------. 1 root root 1850 Oct 22 12:11 anaconda-ks.cfg
  10.  
  11. [root@localhost ~]# \\kevin
  12. -bash: \kevin: command not found
  13.  
  14. [root@localhost ~]# \\kevin -l
  15. -bash: \kevin: command not found
  16.  
  17. \ 单倒斜线:放在特殊符号前,则该特殊符号的作用消失。即转义符号
  18. =======================================
  19. [root@VM_16_9_centos ~]# bkdir=/home
  20. [root@VM_16_9_centos ~]# echo "this is ${bkdir}"
  21. this is /home
  22. [root@VM_16_9_centos ~]# echo "this is \${bkdir}"
  23. this is ${bkdir}
  24. [root@VM_16_9_centos ~]# echo \"this is ${bkdir}\"
  25. "this is /home"
  26. [root@VM_16_9_centos ~]# echo \"this is \${bkdir}\"
  27. "this is ${bkdir}"

|    管道 (pipeline)
pipeline 是 Linux系统中基础且重要的观念。连结上个指令的标准输出,做为下个指令的标准输入。

  1. [root@VM_16_9_centos ~]# who
  2. root pts/0 2019-11-28 22:49 (115.171.60.14)
  3. root pts/1 2019-11-28 23:01 (115.171.60.14)
  4. [root@VM_16_9_centos ~]# who | wc -l
  5. 2

善用这个观念,对精简 script 有相当的帮助。

!    惊叹号(negate or reverse)
通常它代表反逻辑的作用,譬如条件侦测中,用 != 来代表"不等于"

  1. [root@VM_16_9_centos ~]# cat a.sh
  2. #!/bin/bash
  3.  
  4. if [ "$?" != 0 ];then
  5. echo "Executes error"
  6. exit 1
  7. fi
  8. [root@VM_16_9_centos ~]# sh a.sh
  9. "Executes error"

在规则表达式中她担任 "反逻辑" 的角色

  1. [root@VM_16_9_centos ~]# touch bo{0,1,2,3,4,5,6,7,8,9}
  2. [root@VM_16_9_centos ~]# ls
  3. bo0 bo1 bo2 bo3 bo4 bo5 bo6 bo7 bo8 bo9
  4. [root@VM_16_9_centos ~]# ls bo{0,1,2,3}
  5. bo0 bo1 bo2 bo3
  6. [root@VM_16_9_centos ~]# ls bo[0-3]
  7. bo0 bo1 bo2 bo3
  8.  
  9. 显示除了bo0-bo3之外的其他文件
  10. [root@VM_16_9_centos ~]# ls bo[!0-3]
  11. bo4 bo5 bo6 bo7 bo8 bo9
  12.  
  13. 显示除了bo5-bo8之外的其他文件
  14. [root@VM_16_9_centos ~]# ls bo[!5-8]
  15. bo0 bo1 bo2 bo3 bo4 bo9

:    内奸指令 
在 bash 中,这是一个内建指令:"什么事都不干",但返回状态值 0。

  1. 什么都不干,返回状态值 0
  2. [root@VM_16_9_centos ~]# echo $?
  3. 0
  4.  
  5. [root@VM_16_9_centos ~]# : > a.txt
  6. 上面这一行,相当于
  7. [root@VM_16_9_centos ~]# cat /dev/null >a.xtt
  8. 不仅写法简短了,而且执行效率也好上许多。

?      问号  
在文件名扩展(Filename expansion)上扮演的角色是匹配一个任意的字元,但不包含 null 字元。

  1. [root@VM_16_9_centos ~]# ls
  2. a12e.txt aae_txt agte.txt akte.txt aste.txt
  3. [root@VM_16_9_centos ~]# ls a?te.txt
  4. agte.txt akte.txt aste.txt
  5. [root@VM_16_9_centos ~]# ls a1?e.txt
  6. a12e.txt
  7. [root@VM_16_9_centos ~]# ls aae?txt
  8. aae_txt

善用她的特点,可以做比较精确的档名匹配。

*    任意个任意字符。任意的单个或多个字符  
相当常用的符号。在文件名扩展(Filename expansion)上,她用来代表任何字元,包含 null 字元。

  1. [root@VM_16_9_centos ~]# ls
  2. a12e.txt aae_txt agte.txt akte.txt a.sh aste.txt
  3. [root@VM_16_9_centos ~]# ls a*e.txt
  4. a12e.txt agte.txt akte.txt aste.txt
  5. [root@VM_16_9_centos ~]# ls a*te.txt
  6. agte.txt akte.txt aste.txt
  7.  
  8. 在运算时,它则代表 "乘法"
  9. [root@VM_16_9_centos ~]# let "fmult=2*3"
  10. [root@VM_16_9_centos ~]# echo ${fmult}
  11. 6
  12.  
  13. 除了内建指令 let,还有一个关于运算的指令expr,星号在这里也担任"乘法"的角色。不过在使用上得小心,他的前面必须加上escape字元(即转义符)。
  14. [root@VM_16_9_centos ~]# expr 2 \* 3
  15. 6

**    次方运算

  1. [root@ss-server ~]# let sum=2**4
  2. [root@ss-server ~]# echo ${sum}
  3. 16
  4. [root@ss-server ~]# echo $((3*3))
  5. 9
  6. [root@ss-server ~]# let sum=2**4
  7. [root@ss-server ~]# echo ${sum}
  8. 16
  9. [root@ss-server ~]# echo $((3**3))
  10. 27
  11. [root@ss-server ~]# echo $[3**4]
  12. 81

$     变量符号、正则里表示"行尾"

  1. $是变量替换的代表符号。
  2. [root@ss-server ~]# var="wang lao hu"
  3. [root@ss-server ~]# echo $var
  4. wang lao hu
  5. [root@ss-server ~]# echo ${var}
  6. wang lao hu
  7.  
  8. 另外:
  9. Regular Expressions里被定义为 \"\" 的最末端。这个常用在grepsedawk 以及 vim(vi) 当中。
  10.  
  11. ^ 表示行首
  12. $ 表示行尾

${}    变量的正规表达式    
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}.....
个位数的,可直接使用数字,但两位数以上,则必须使用 {} 符号来括住。 具体使用含义后面有详细说明
$*  则是代表所有引用变量的符号。使用时,得视情况加上双引号。

  1. [root@ss-server ~]# echo "$*"
  2. ""
  3. [root@ss-server ~]# echo "$*"
  4.  
  5. [root@ss-server ~]# cat test.sh
  6. #!/bin/bash
  7. USER=$1
  8. AGE=$2
  9. ADD=$3
  10. HE=$4
  11.  
  12. echo "$1 is $2,come from $3,and $4"
  13. echo "$*"
  14.  
  15. [root@ss-server ~]# sh test.sh 张阳 20 安徽 帅气
  16. 张阳 is 20,come from 安徽,and 帅气
  17. 张阳 20 安徽 帅气

$@    所有引用的变量
$@ 与 $* 具有相同作用的符号,不过它们两者有一个不同点。
符号 $* 将所有的引用变量视为一个整体。但符号 $@ 则仍旧保留每个引用变量的区段观念。 [ $@ 与 $* 二者的区别在下面会详细提到]

$#    参数变量的总数量  
这也是与引用变量相关的符号,它的作用是告诉你,引用变量的总数量是多少。

  1. [root@ss-server ~]# cat a.sh
  2. #!/bin/bash
  3. USER=$1
  4. AGE=$2
  5. ADD=$3
  6. HE=$4
  7.  
  8. echo "$1 is $2,come from $3,and $4"
  9. echo "$*"
  10. echo "$@"
  11. echo "$#"
  12. [root@ss-server ~]# sh a.sh 黄涛 30 杭州
  13. 黄涛 is 30,come from 杭州,and
  14. 黄涛 30 杭州
  15. 黄涛 30 杭州
  16. 3
  17. [root@ss-server ~]# echo "$#"
  18. "0"
  19. [root@ss-server ~]# echo "$#"
  20. 0

$?    状态值 (status variable)
一般来说,Linux 系统的进程以执行系统调用exit()来结束的。这个回传值就是status值。回传给父进程,用来检查子进程的执行状态。
一般指令程序倘若执行成功,其$?回传值为 0;若执行失败,则$?回传值为 1。

  1. [root@ss-server ~]# ls a.sh
  2. a.sh
  3. [root@ss-server ~]# echo $?
  4. 0
  5. [root@ss-server ~]# ls aa.sh
  6. ls: cannot access aa.sh: No such file or directory
  7. [root@ss-server ~]# echo $?
  8. 2

$$    当前shell的PID
由于进程的ID是唯一的,所以在同一个时间,不可能有重复性的 PID。有时,script会需要产生临时文件,用来存放必要的资料。而此script亦有可能在同一时间被使用者们使用。在这种情况下,固定文件名在写法上就显的不可靠。唯有产生动态文件名,才能符合需要。符号$$或许可以符合这种需求。它代表当前shell 的 PID。

  1. [root@ss-server ~]# echo "hello world"
  2. hello world
  3. [root@ss-server ~]# echo $$
  4. 78520
  5. [root@ss-server ~]# echo "hello world" > aa.$$
  6. [root@ss-server ~]# cat aa.78520
  7. hello world
  8.  
  9. [root@ss-server ~]# cat a.sh
  10. #!/bin/bash
  11. USER=$1
  12. AGE=$2
  13. ADD=$3
  14. HE=$4
  15.  
  16. echo "$1 is $2,come from $3,and $4"
  17. echo "$#"
  18. echo "$*"
  19. echo "$@"
  20. echo "$$"
  21. echo "$0"
  22. [root@bz3aomsmsap1002 ~]sh a.sh 张阳 20 安徽 帅气
  23. 张阳 is 20,come from 安徽,and 帅气
  24. 4
  25. 张阳 20 安徽 帅气
  26. 张阳 20 安徽 帅气
  27. 90261
  28. a.sh

使用它来作为文件名的一部份,可以避免在同一时间,产生相同文件名的覆盖现象。
基本上,系统会回收执行完毕的 PID,然后再次依需要分配使用。所以 script 即使临时文件是使用动态档名的写法,如果script 执行完毕后仍不加以清除,会产生其他问题。

( )    指令群组 (command group)
用括号将一串连续指令括起来,这种用法对 shell 来说,称为指令群组。如下面的例子:

  1. [root@ss-server ~]# (cd ~ ; pwstr=`pwd` ;echo ${pwstr})
  2. /root

指令群组有一个特性,shell会以产生 subshell来执行这组指令。因此,在其中所定义的变数,仅作用于指令群组本身。来看个例子:

  1. [root@ss-server ~]# cat a.sh
  2. #!/bin/bash
  3. a=wang
  4. b=zhang
  5. (a=han ; echo -e "\n $a \n")
  6. (b=xiaoru; echo -e "this is $b")
  7. echo $a
  8. echo $b
  9.  
  10. [root@ss-server ~]# sh a.sh
  11.  
  12. han
  13.  
  14. this is xiaoru
  15. wang
  16. zhang
  17.  
  18. 由上面可知:shell的指令群组所定义的变数,仅作用于指令群组本身。
  19.  
  20. 来看看echo的几个操作效果
  21. =============================================================
  22. [root@ss-server ~]# echo "aa"
  23. aa
  24. [root@ss-server ~]# echo \"aa\"
  25. "aa"
  26. [root@ss-server ~]# echo -e "\n wang \n"
  27.  
  28. wang
  29.  
  30. [root@ss-server ~]# echo -e \"\n wang \n\" # 这种情况下,\n就不是换行符了,因为双引号也被转义了。
  31. "n wang n"

除了上述的指令群组,括号也用在 array数组变数的定义上;另外也应用在其他可能需要加上escape字元才能使用的场合,如运算式。

(( ))
这组符号的作用与 let 指令相似,用在算数运算上,是 bash 的内建功能。所以,在执行效率上会比使用 let指令要好许多。

  1. [root@ss-server ~]# cat a.sh
  2. #!/bin/bash
  3.  
  4. (( a = 10 ))
  5. echo -e "inital value, a = $a\n"
  6.  
  7. (( a++))
  8. echo "after a++, a = $a"
  9.  
  10. [root@ss-server ~]# sh a.sh
  11. inital value, a = 10
  12.  
  13. after a++, a = 11

请记住:
$(())、$[]    这两个效果是一样的,都是运算符号,显示运算结果。
let     也是运算符号,设置运算

  1. [root@ss-server ~]# echo $((4*9))
  2. 36
  3. [root@ss-server ~]# echo $[4*9]
  4. 36
  5. [root@ss-server ~]# let a=4*9
  6. [root@ss-server ~]# echo $a
  7. 36
  8. [root@ss-server ~]# let "a=4*9"
  9. [root@ss-server ~]# echo $a
  10. 36
  11. [root@ss-server ~]# let a="3+5"
  12. [root@ss-server ~]# echo $a
  13. 8
  14.  
  15. [root@ss-server ~]# a=10
  16. [root@ss-server ~]# let a++ #表示变量a数值加1
  17. [root@ss-server ~]# echo $a
  18. 11

{ } 大括号 
这种大括号的组合,常用在字串的组合上,来看个例子

  1. [root@ss-server ~]# mkdir aa{1,2,3}
  2. [root@ss-server ~]# ls
  3. aa1 aa2 aa3
  4. [root@ss-server ~]# ll -d bb1*
  5. drwxr-xr-x 2 root root 4096 Dec 5 11:37 bb1-k01
  6. drwxr-xr-x 2 root root 4096 Dec 5 11:37 bb1-k02
  7. drwxr-xr-x 2 root root 4096 Dec 5 11:37 bb1-k03
  8. [root@ss-server ~]# ll -d cc1*
  9. drwxr-xr-x 2 root root 4096 Dec 5 11:37 cc1-k01
  10. drwxr-xr-x 2 root root 4096 Dec 5 11:37 cc1-k02
  11. drwxr-xr-x 2 root root 4096 Dec 5 11:37 cc1-k03
  12. [root@ss-server ~]# ll -d dd1*
  13. drwxr-xr-x 2 root root 4096 Dec 5 11:37 dd1-k01
  14. drwxr-xr-x 2 root root 4096 Dec 5 11:37 dd1-k02
  15. drwxr-xr-x 2 root root 4096 Dec 5 11:37 dd1-k03
  16. [root@ss-server ~]# touch {wan,han}_{1,2,3}
  17. [root@ss-server ~]# ls wan*
  18. wan_1 wan_2 wan_3
  19. [root@ss-server ~]# ls han*
  20. han_1 han_2 han_3
  21. [root@ss-server ~]# chmod 755 /root/wan_{1,2,3}
  22. [root@ss-server ~]# ll /root/wan_{1,2,3}
  23. -rwxr-xr-x 1 root root 0 Dec 5 11:39 /root/wan_1
  24. -rwxr-xr-x 1 root root 0 Dec 5 11:39 /root/wan_2
  25. -rwxr-xr-x 1 root root 0 Dec 5 11:39 /root/wan_3

这组符号在适用性上相当广泛。能加以善用的话,回报是精简与效率。像下面的例子

  1. ?表示任意单个字符!!!
  2. [root@ss-server ~]# chown app.app /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}

如果不是因为支援这种用法,我们得写几行重复几次呀!

[ ] 中括号
常出现在流程控制中,扮演括住判断式的作用。

  1. [root@ss-server ~]# ls hahaha
  2. ls: cannot access hahaha: No such file or directory
  3. [root@ss-server ~]# echo $?
  4. 2
  5.  
  6. [root@ss-server ~]# cat a.sh
  7. #!/bin/bash
  8.  
  9. ls hahaha >/dev/null 2>&1
  10. if [ "$?" != 0 ];then
  11. echo "Executes error"
  12. exit 1
  13. fi
  14.  
  15. [root@ss-server ~]# sh a.sh
  16. Executes error

这个符号在正则表达式中担任类似 "范围" 或 "集合" 的角色

  1. [root@ss-server ~]# touch aaa{1,2,3,4}
  2. [root@ss-server ~]# ls aaa*
  3. aaa1 aaa2 aaa3 aaa4
  4. [root@ss-server ~]# rm -f aaa[1234]
  5. [root@ss-server ~]# ls aaa*
  6. ls: cannot access aaa*: No such file or directory
  7.  
  8. 注意:
  9. rm -f aaa[1234] 表示删除aaa1aaa2aaa3aaa4
  10. 相当于
  11. rm -f aaa{1,2,3,4}
  12.  
  13. 注意:
  14. 只有在删除文件的时候,[]可以起到上面类似 "范围" "集合" 的角色!
  15. 在其他操作都不会起到该作用!
  16.  
  17. 如下,在touch的时候,[]并没有起到范围或集合的作用!
  18. [root@ss-server ~]# touch aa[123]
  19. [root@ss-server ~]# touch aa[123]_[xyz]
  20. [root@ss-server ~]# ls aa*
  21. aa[123] aa[123]_[xyz]

[[ ]]
这组符号与先前的 [] 符号,基本上作用相同,但它允许在其中直接使用 || 与&& 逻辑等符号。||表示"或",&&表示"和" 。双中括号[[]]和单中括号[]的区别,在下面会详细提到。

  1. [root@ss-server ~]# cat a.sh
  2. #!/bin/bash
  3. read -p "请输入一个数字: " num
  4. if [[ ${num} > 10 && ${num}< 30 ]];then
  5. echo "你输入的数字是${num}"
  6. else
  7. echo "输入的数字不符合要求"
  8. fi
  9.  
  10. [root@ss-server ~]# sh a.sh
  11. 请输入一个数字: 16
  12. 你输入的数字是16
  13. [root@ss-server ~]# sh a.sh
  14. 请输入一个数字: 56
  15. 输入的数字不符合要求
  16.  
  17. 上面脚本还可以改写为下面内容,效果是一样的!
  18. [root@ss-server ~]# cat a.sh
  19. #!/bin/bash
  20.  
  21. #echo -n表示不换行
  22. echo -n "输入一个数字: "
  23. read num
  24. if [[ ${num} > 10 && ${num}< 30 ]];then
  25. echo "你输入的数字是${num}"
  26. else
  27. echo "输入的数字不符合要求"
  28. fi
  29.  
  30. [root@ss-server ~]# sh a.sh
  31. 输入一个数字: 19
  32. 你输入的数字是19
  33. [root@ss-server ~]# sh a.sh
  34. 输入一个数字: 48
  35. 输入的数字不符合要求
  36.  
  37. ===============================================
  38. 需要注意:
  39. if判断语句中如果使用[[]],可以在[[]]中直接使用&&、||符号,表示"和""或"。可以用于字符串对比符号,也可以用于整数对比符号。
  40. if判断语句中如果使用[],在[]中可以使用-a、-o,表示"和""或",但是这个用于整数比较时只能使用"-eq、-ne、-ge、-gt、-lt、-le",不能使用>、>=、<、<=、=、!=。
  41.  
  42. [root@ss-server ~]# cat a.sh
  43. #!/bin/bash
  44. read -p "请输入一个数字: " num
  45. if [ ${num} -gt 10 -a ${num} -le 30 ];then
  46. echo "你输入的数字是${num}"
  47. else
  48. echo "输入的数字不符合要求"
  49. fi
  50.  
  51. [root@ss-server ~]# sh a.sh
  52. 请输入一个数字: 12
  53. 你输入的数字是12
  54. [root@ss-server ~]# sh a.sh
  55. 请输入一个数字: 45
  56. 输入的数字不符合要求
  57.  
  58. 上面脚本中的[ ${num} -gt 10 -a ${num} -le 30 ]
  59. 不能改为:
  60. [ ${num} -ge 10 ] -a [${num} -le 30 ]
  61. 也不能改为
  62. [ ${num} > 10 -a ${num} < 30 ]
  63.  
  64. [[]]的&&、||也可以用于整数对比。
  65. [root@ss-server ~]# cat a.sh
  66. #!/bin/bash
  67. read -p "请输入一个数字: " num
  68. if [[ ${num} -ge 10 && ${num} -le 30 ]];then
  69. echo "你输入的数字是${num}"
  70. else
  71. echo "输入的数字不符合要求"
  72. fi
  73. [root@ss-server ~]# sh a.sh
  74. 请输入一个数字: 17
  75. 你输入的数字是17
  76. [root@ss-server ~]# sh a.sh
  77. 请输入一个数字: 67
  78. 输入的数字不符合要求

||     逻辑符号 
这个会时常看到,代表 or 逻辑的符号,表示前一个命令执行成功,则就此结束,后一个命令就不执行;前一个命令执行失败,后一个命令才会执行。如 A || B  表示A执行成功后,B就不会再执行了;A执行失败或不执行,B才能执行。

&&     逻辑符号
这个也会常看到,代表 and 逻辑的符号,表示串行,即前一个命令执行成功,后一个命令才接着执行;前一个命令执行失败,则就此结束,后一个命令也不会执行。如 A && B  表示A执行成功后,B也会跟着执行了;A执行失败或不执行,B也不会执行了。

&     后台工作
单一个& 符号,且放在完整指令列的最后端,即表示将该指令列放入后台中工作。 放在几个指令中间时,表示并行,实质就是在后台并行执行,跟指令前后顺序无关。

  1. [root@ss-server ~]# tar -zvcf test1.tar.gz test1 > /dev/null &

\<...\>   单字边界
这组符号在规则表达式中,被定义为\"边界\"的意思。如下想要在test文件中找寻 the 这个单字时,如果我们用

  1. [root@ss-server ~]# cat test
  2. the
  3. there
  4. this is a
  5. 123456
  6. thee
  7. [root@ss-server ~]# grep "the" test
  8. the
  9. there
  10. thee

如上会发现,像 there、thee这类的单字,也会被当成是匹配的单字。因为 the 正巧是there、thee的一部份。如果要想必免这种情况,就得加上单字边界符号,进行精准匹配:

  1. [root@ss-server ~]# cat test
  2. the
  3. there
  4. this is a
  5. 123456
  6. thee
  7. [root@ss-server ~]# grep "the" test
  8. the
  9. there
  10. thee
  11. [root@ss-server ~]# grep "\<the\>" test
  12. the
  13.  
  14. 另外:上面在进行grep精准匹配时,除了使用\<str\>单字边界符号,还可以使用grep -w进行精准匹配!
  15. [root@ss-server ~]# cat test
  16. the
  17. there
  18. this is a
  19. 123456
  20. thee
  21. [root@ss-server ~]# grep -w "the" test
  22. the
  23.  
  24. 可以参考:https://www.cnblogs.com/kevingrace/p/9299232.html

+    加号 
在运算式中,她用来表示 "加法"。

  1. [root@ss-server ~]# expr 10 + 11 + 12
  2. 33
  3.  
  4. 注意:expr命令中的计算符号和数字中间一定要有空格!!否则无效!并且后面的运算两边不能有引号,否则也无效!
  5.  
  6. 下面都是错误的!!
  7. [root@ss-server ~]# expr 10+11+12
  8. 10+11+12
  9. [root@ss-server ~]# expr "10 + 11 + 12"
  10. 10 + 11 + 12
  11.  
  12. 另外:注意expr使用*乘法的时候,需要在*前面加上转义符号\,否则无效!
  13. [root@ss-server ~]# expr 2 * 3
  14. expr: syntax error
  15. [root@ss-server ~]# expr 2 \* 3
  16. 6

此外在正则表达式中,用来表示"很多个"的前面字元的意思。但是注意,正则里使用+符号表示"很多个"意思时,+号前面必须加上\\符号!!

  1. [root@ss-server ~]# cat test
  2. 123456
  3. 10aaaahuihhhhh
  4. s34eddddd
  5. kkkhuan
  6. [root@ss-server ~]# grep "10\\+a" test
  7. 10aaaahuihhhhh
  8. [root@ss-server ~]# grep "e\\+d" test
  9. s34eddddd
  10. [root@ss-server ~]# grep "\\k" test
  11. kkkhuan

-     减号 
在运算式中,她用来表示 "减法"。

  1. [root@ss-server ~]# expr 10 - 2
  2. 8

在 cd 指令中则比较特别,"cd -"表示变更工作目录到\"上一次\"工作目录。

  1. [root@ss-server ~]# cd /usr/local/src/
  2. [root@bz3aomsmsap1002 src]# cd
  3. [root@ss-server ~]# cd -
  4. /usr/local/src
  5. [root@bz3aomsmsap1002 src]#

%      除法后的余数 
在运算式中,用来表示 "除法"后的余数。 [运算式中的乘法*,用的时候需要在前面加一个转移符   expr  5 \* 10]

  1. [root@ss-server ~]# expr 10 % 2
  2. 0
  3. [root@ss-server ~]# expr 10 % 3
  4. 1
  5. [root@ss-server ~]# expr 10 % 6
  6. 4
  7. [root@ss-server ~]# expr 6 % 9
  8. 6
  9. [root@ss-server ~]# expr 6 % 90
  10. 6
  11. [root@ss-server ~]# expr 5 % 6
  12. 5
  13.  
  14. %表示余数,即整除后的余数是多少。
  15. 如果小除大,则%余数统一为前面那个小的数。

此外,也被运用在关于变量的规则表达式当中的下列

  1. ${parameter%word}
  2. ${parameter%%word}
  3.  
  4. 一个 % 表示最短的 word 匹配,两个表示最长的 word 匹配。
  5. 可以参考上面"参数替换"部分有详细介绍

=      等号
常在设定变数时看到的符号。

  1. [root@ss-server ~]# vara="hello world"
  2. [root@ss-server ~]# echo "vara=${vara}"
  3. 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) 示例1
  2. [root@ss-server ~]# cat a.sh
  3. #!/bin/bash
  4.  
  5. for i in $*
  6. do
  7. echo $i
  8. done
  9.  
  10. echo "++++++ \$*和\$@对比(不加双引号) ++++++"
  11.  
  12. for j in $@
  13. do
  14. echo $j
  15. done
  16.  
  17. [root@ss-server ~]# sh a.sh aa bb cc
  18. aa
  19. bb
  20. cc
  21. ++++++ $*和$@对比(不加双引号) ++++++
  22. aa
  23. bb
  24. cc
  25.  
  26. 2) 示例2
  27. [root@ss-server ~]# cat a.sh
  28. #!/bin/bash
  29.  
  30. for i in "$*"
  31. do
  32. echo $i
  33. done
  34.  
  35. echo "++++++ \$*和\$@对比(加双引号) ++++++"
  36.  
  37. for j in "$@"
  38. do
  39. echo $j
  40. done
  41. [root@ss-server ~]# sh a.sh aa bb cc
  42. aa bb cc
  43. ++++++ $*和$@对比(加双引号) ++++++
  44. aa
  45. bb
  46. cc
  47.  
  48. 3)示例3,在一个shell函数里分别定义 加双引号和不加双引号 传参时,$@$*的区别
  49. [root@ss-server ~]# cat a.sh
  50. #! /bin/bash
  51.  
  52. function test() {
  53. echo "未加引号,二者相同"
  54. echo $*
  55. echo $@
  56. echo "加入引号后对比"
  57.  
  58. echo "----"\$*----""
  59. for N in "$*"
  60. do
  61. echo $N
  62. done
  63.  
  64. echo "----"\$@----""
  65. for N in "$@"
  66. do
  67. echo $N
  68. done
  69. }
  70. test 11 22 33
  71. [root@ss-server ~]# sh a.sh
  72. 未加引号,二者相同
  73. 11 22 33
  74. 11 22 33
  75. 加入引号后对比
  76. ----$*----
  77. 11 22 33
  78. ----$@----
  79. 11
  80. 22
  81. 33
  82.  
  83. ====================================================================================
  84. 通过上面对比,可以发现:
  85. 不加引号时,$*和$@二者都是返回传入的参数;
  86. 加了引号后,$*把参数作为一个字符串整体(单字符串)返回,$@把每个参数作为一个字符串返回!

命令列表 
and列表   statement1 && statement2  && .....   表示只有在前面所有的命令都执行成功的情况下才执行后一条命令;即前面成功,后面继续执行;前面失败,后面也不执行!
or列表      statement1 || statement2  || …..   表示允许执行一系列命令直到有一条命令成功为止,其后所有命令将不再被执行;即前面成功,后面不执行;前面失败,后面执行!!

  1. [root@ss-server ~]# cat a.sh
  2. #!/bin/bash
  3.  
  4. touch file_one >/dev/null 2>&1
  5. rm -f file_two >/dev/null 2>&1
  6.  
  7. if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo " there";then
  8. echo "in if"
  9. else
  10. echo "in else"
  11. fi
  12. exit 0
  13. [root@ss-server ~]# sh a.sh
  14. hello
  15. in else

if逻辑判断语句中常用到的参数 以及 注意细节 (如[[]]和[]的区别)

  1. [ -a file ] 如果 file 存在则为真。
  2. [ -e file ] 如果 file 存在则为真。
  3.  
  4. [ -f file ] 如果 file 存在且是一个普通文件则为真。
  5. [ -d file ] 如果 file 存在且是一个目录则为真。
  6.  
  7. [ -b file ] 如果 file 存在且是一个块特殊文件则为真。(即设备文件,如/dev/sda1、/dev/sda2)
  8.  
  9. [ -h file ] 如果 file 存在且是一个符号文件则为真。(符号文件即是软链接文件)
  10. [ -L file ] 如果 file 存在且是一个符号文件则为真。(符号文件即是软链接文件)
  11.  
  12. [ -g file ] 如果 file 存在且已经设置了SGID则为真。
  13. [ -u file ] 如果 file 存在且设置了SUID则为真。
  14. [ -k file ] 如果 file 存在且已经设置了粘制位则为真。(即设置了t权限的目录,粘制位仅对目录有效)
  15.  
  16. [ -r file ] 如果 file 存在且是可读的则为真。
  17. [ -w file ] 如果 file 存在且是可写的则为真。
  18. [ -x file ] 如果 file 存在且是可执行的则为真。
  19.  
  20. [ -s file ] 如果 file 存在且大小不为0则为真。
  21.  
  22. [ -O file ] 如果 file 存在且属有效用户ID则为真。
  23. [ -G file ] 如果 file 存在且属有效用户组则为真。
  24.  
  25. [ file1 -nt file2 ] 如果 file1 file2 要老(即先创建), 或者 file1 存在且 file2不存在则为真。
  26. [ file1 -ot file2 ] 如果 file1 file2 要老(即先创建), 或者 file2 存在且 file1 不存在则为真。
  27.  
  28. [ -z str ] 如果str字符串的长度为零则为真。 (即空串为真)
  29. [ -n str ] or [ str ] 如果str字符串的长度为非零则为真。 (即非空串为真)
  30.  
  31. [ str1 == str2 ] 如果2个字符串相同则为真。
  32. [ str1 != str2 ] 如果字符串不相等则为真。
  33.  
  34. 二、简单总结
  35. ===========================================================================
  36. 1)字符串判断
  37. str1 = str2     当两个串有相同内容、长度时为真
  38. str1 != str2     当串str1str2不等时为真
  39. -n str1       当串的长度大于0时为真(串非空)
  40. -z str1       当串的长度为0时为真(空串)
  41. str1         当串str1为非空时为真。等于"-n star1"
  42.  
  43. 2)数字的判断
  44. int1 -eq int2    两数相等为真
  45. int1 -ne int2    两数不等为真
  46. int1 -gt int2    int1大于int2为真
  47. int1 -ge int2    int1大于等于int2为真
  48. int1 -lt int2    int1小于int2为真
  49. int1 -le int2    int1小于等于int2为真
  50.  
  51. 3)文件的判断
  52. -a file 文件存在为真
  53. -z file 文件存在为真
  54. -r file     用户可读为真
  55. -w file     用户可写为真
  56. -x file     用户可执行为真
  57. -f file     文件为普通文件为真
  58. -d file     文件为目录为真
  59. -s file     文件大小非0时为真
  60. -h file 文件为符号文件为真
  61. -L file 文件为符号文件为真
  62. -g file 文件为SGID权限文件为真
  63. -u file 文件为SUID权限文件为真
  64. -k file 文件为T权限文件为真
  65.  
  66. 4)复杂逻辑判断
  67. -a     
  68. -o    或
  69. !     非
  70.  
  71. 三、注意细节
  72. ===========================================================================
  73. 1)在if的中括号中,判断变量的值,加不加双引号的问题?
  74. -z 判断变量的值,是否为空:
  75. 变量的值,为空,返回0,为true
  76. 变量的值,非空,返回1,为false
  77. -n 判断变量的值,是否为空:
  78. 变量的值,为空,返回1,为false
  79. 变量的值,非空,返回0,为true
  80. str="abc"
  81. [ -z "$str" ] 单中括号,变量必须要加双引号!
  82. [[ -z $str ]] 双中括号,变量不用加双引号
  83.  
  84. [ -n "$str" ] 单中括号,变量必须要加双引号!
  85. [[ -n $str ]] 双中括号,变量不用加双引号
  86.  
  87. 2)多个条件判断,[] [[]] 的区别????????????????????
  88. && 并且,相当于and
  89. || 或,相当于or
  90.  
  91. -a 并且,相当于and
  92. -o 或者,相当于or
  93.  
  94. --------------------------------------------
  95. 2.1)双中括号[[]]的条件判断
  96. [[ ]] 双中括号的条件判断用"&&" "||"
  97.  
  98. || 满足一个条件满足就成立;或者的关系
  99. [[ $a -lt 3 || $a -gt 6 ]]
  100. [[ $a -lt 3 ]] || [[ $a -gt 6 ]] # 写在外面也可以
  101.  
  102. && 必须同时满足两个条件同时;并且的关系。
  103. [[ $a -gt 3 && $a -lt 10 ]]
  104. [[ $a -gt 3 ]] && [[$a -lt 10 ]] # 写在外面也可以
  105.  
  106. 这里需要注意的问题的是:
  107. [[]]双中括号的判断语句中,只能使用&&和||,可以在[[]]内部使用,也可以在[[]]外面使用!
  108. [[]]双中括号的判断语句中不能使用-a和-o参数!!!!!!
  109.  
  110. 如果使用下面写法就是错误的!!!!!!
  111. [[ $a -lt 3 -o $a -gt 6 ]]
  112. [[ $a -lt 3 ]] -o [[ $a -gt 6 ]]
  113. [[ $a -gt 3 -a $a -lt 10 ]]
  114. [[ $a -gt 3 ]] -a [[$a -lt 10 ]]
  115.  
  116. --------------------------------------------
  117. 2.2)单中括号[]的条件判断
  118. [ ] 单中括号的条件判断可以使用-a和-o的参数,但是必须在单[ ]中括号内判断条件!!不能在单中括号外面!!
  119. [ $a -lt 10 -o $a -gt 20 ] 这个"或者"条件成立
  120. [ $a -lt 10 ] -o [ $a -gt 20 ] 这个"或者"不成立,因为必须在中括号内判断!!!!
  121.  
  122. 如果想在[]中括号外判断两个条件,必须用&& || 比较!
  123. [ $a -lt 10 ] || [ $a -gt 20 ] 这个"或者"条件成立
  124. [ $a -lt 10 ] && [ $a -gt 20 ] 这个"并且"条件成立
  125.  
  126. 同样需要注意:|| && 不能在单中括号[]内使用,只能在单中括号[]外面使用!!!
  127.  
  128. 3) 当判断某个变量的值是否满足正则表达式的时候,必须使用[[ ]] 双中括号!!!!
  129. 示例:
  130. [root@ss-server ~]# str=13611082178
  131. [root@ss-server ~]# [[ ${str} =~ [0-9]{11} ]]
  132. [root@ss-server ~]# echo $?
  133. 0
  134.  
  135. 如果使用单中括号,会直接报错:
  136. [root@ss-server ~]# str=13611082178
  137. [root@ss-server ~]# [ ${str} =~ [0-9]{11} ]
  138. -bash: [: =~: binary operator expected
  1. shell脚本获取第10个参数
  2.  
  3. Shell脚本中,可以用$n的方式获取第n个参数
  4. [root@ansible-server ~]# cat a.sh
  5. #!/bin/bash
  6. echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}
  7.  
  8. [root@ansible-server ~]# sh a.sh a b c d 1 2 3 4 8 ab
  9. a b c d 1 2 3 4 8 ab
  10.  
  11. 取第10个参数, 要用${10}, 不能使用$10(这个表示第1个参数加上0)。因为个位数的参数,可以直接使用数字。但两位以上数字的参数,必须使用{}符号!!!!
  12. #!/bin/bash
  13. echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10
  14.  
  15. [root@ansible-server ~]# sh a.sh a b c d 1 2 3 4 8 ab
  16. a b c d 1 2 3 4 8 a0
  17.  
  18. 即上面脚本中$10 取的值为$1+0
  19.  
  20. 再看几个例子
  21. [root@ansible-server ~]# cat a.sh
  22. #!/bin/bash
  23. #echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10
  24. echo $3 $12
  25.  
  26. [root@ansible-server ~]# sh a.sh a b c d 1 2 3 4 8 ab
  27. c a2
  28.  
  29. [root@ansible-server ~]# cat a.sh
  30. #!/bin/bash
  31. #echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10
  32. echo $3 ${12}
  33.  
  34. [root@ansible-server ~]# sh a.sh a b c d 1 2 3 4 8 ab bo kevin
  35. c kevin

$#    是传递给脚本的参数个数;
$0    是脚本本身的名字;
$1    是传递给该shell脚本的第一个参数;
$2    是传递给该shell脚本的第二个参数;
$@   是传递给脚本的所有参数的列表(是多个字符串,每个参数为1个字符串);
$*     是传递给脚本的所有参数的列表(以一个单字符串显示所有参数),与位置变量不同,参数可超过9个;
$$    是运行脚本的当前进程ID号;
$?    是显示执行上一条Shell命令的返回值,0表示没有错误,其他表示有错误。

  1. 如下,用一个简单的脚本来说明上面这些变量的含义
  2. [root@kevin ~]# vim /root/path.sh
  3. #!/bin/sh
  4. echo "the number of parameters passed to the script: $#"
  5. echo "the name of the script itself: $0"
  6. echo "the first parameter passed to the shell script: $1"
  7. echo "the second parameter passed to the shell script: $2"
  8. echo "the list of all the parameters passed to the script(some string): $@"
  9. echo "the list of all the parameters passed to the script(one string): $*"
  10. echo "the current process ID number of the script which is running: $$"
  11. echo "the return value of the last shell command performed: $?"
  12.  
  13. [root@kevin ~]# chmod 755 /root/path.sh
  14. [root@kevin ~]# ll /root/path.sh
  15. -rwxr-xr-x. 1 root root 512 Jun 25 11:21 /root/path.sh
  16.  
  17. [root@kevin ~]# sh /root/path.sh 10 20 30
  18. the number of parameters passed to the script: 3
  19. the name of the script itself: /root/path.sh
  20. the first parameter passed to the shell script: 10
  21. the second parameter passed to the shell script: 20
  22. the list of all the parameters passed to the script(some string): 10 20 30
  23. the list of all the parameters passed to the script(one string): 10 20 30
  24. the current process ID number of the script which is running: 372
  25. the return value of the last shell command performed: 0

Shell脚本常用命令 -exit 和 if

  1. 1exit
  2. exit 0 退出shell,成功
  3. exit 1 退出shell,失败
  4. exit 2 退出shell,用法不当
  5.  
  6. 需要注意:
  7. 如果shell脚本中调用的子脚本的exit,那么会退出子脚本
  8. 如果是source一个子脚本,里面的exit会导致外面的脚本也退出
  9.  
  10. ==============================================================
  11. 2if
  12. 1) if [-z "$name"]
  13. 判断name是否为空字符串,如果空,则为真,执行if的内容
  14. 等同于 if ["$name" = ""]
  15. 等同于[! "$name"]
  16.  
  17. 2) if的几个参数
  18. -z 字符串是否为空,空为真
  19. -n 指定字符串是否不空,不空为真
  20. -a 某东西不存在,则为真。不限定为字符串
  21. -f 普通文件是否存在
  22. -d 目录是否存在
  23. -e 某东西是否存在,不限定为文件

                                                                                                                                             
Shell脚本中判断参数是否为空,如果为空就停止后续操作

  1. 注意下面的方法
  2. if [ str1 = str2 ]  当两个串有相同内容、长度时为真
  3. if [ str1 != str2 ] 当串str1str2不等时为真
  4. if [ -n str1 ]    当串的长度大于0时为真(串非空) 注意: 这个等同于if [ ! -n str1 ] ,前提是里面的str1不加上"",如果加上""就等同于if [ -z str1 ]了!
  5. if [ -z str1 ]    当串的长度为0时为真(空串) 注意:这个等同于 if [ ! -n "str1" ],前提是str1必须要加上""双引号!!
  6.  
  7. ==================================================================
  8. [root@bz3aomsmsap1002 mnt]# cat test.sh
  9. #!/bin/bash
  10. AN=""
  11. BN="sadf"
  12. if [ -z ${AN} ];then
  13. echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
  14. exit 1
  15. fi
  16.  
  17. echo "结果为:${AN} is a good ${BN}"
  18.  
  19. [root@bz3aomsmsap1002 mnt]# sh test.sh
  20. 没有变量AN,无法执行后续操作,请确认输入了AN参数
  21.  
  22. -----------------------------------------
  23. [root@bz3aomsmsap1002 mnt]# cat test.sh
  24. #!/bin/bash
  25. AN="ha"
  26. BN="sadf"
  27. if [ -z ${AN} ];then
  28. echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
  29. exit 1
  30. fi
  31.  
  32. echo "结果为:${AN} is a good ${BN}"
  33.  
  34. [root@bz3aomsmsap1002 mnt]# sh test.sh
  35. 结果为:ha is a good sadf
  36.  
  37. ==================================================================
  38. 如果要想使用-n代替-z,则做法如下:
  39. 必须注意:
  40. 下面的if判断语句中的-n后面的变量必须要加上双引号""!否则就失效!
  41. 因为如果不加""的话,就等同于了效于if [ -n ]
  42. [root@bz3aomsmsap1002 mnt]# cat test.sh
  43. #!/bin/bash
  44. AN=""
  45. BN="sadf"
  46. if [ ! -n "${AN}" ];then
  47. echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
  48. exit 1
  49. fi
  50.  
  51. echo "结果为:${AN} is a good ${BN}"
  52.  
  53. [root@bz3aomsmsap1002 mnt]# sh test.sh
  54. 没有变量AN,无法执行后续操作,请确认输入了AN参数
  55.  
  56. -----------------------------------------
  57. [root@bz3aomsmsap1002 mnt]# cat test.sh
  58. #!/bin/bash
  59. AN="ru"
  60. BN="sadf"
  61. if [ ! -n "${AN}" ];then
  62. echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
  63. exit 1
  64. fi
  65.  
  66. echo "结果为:${AN} is a good ${BN}"
  67.  
  68. [root@bz3aomsmsap1002 mnt]# sh test.sh
  69. 结果为:ru is a good sadf
  70.  
  71. -----------------------------------------
  72. 如果不加双引号,则if [ ! -n ] 就等同于了 -f [ -n ]
  73.  
  74. [root@bz3aomsmsap1002 mnt]# cat test.sh
  75. #!/bin/bash
  76. AN=""
  77. BN="sadf"
  78. if [ ! -n ${AN} ];then
  79. echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
  80. exit 1
  81. fi
  82.  
  83. echo "结果为:${AN} is a good ${BN}"
  84.  
  85. [root@bz3aomsmsap1002 mnt]# sh test.sh
  86. 结果为: is a good sadf
  87.  
  88. -----------------------------------------
  89. [root@bz3aomsmsap1002 mnt]# cat test.sh
  90. #!/bin/bash
  91. AN="ru"
  92. BN="sadf"
  93. if [ ! -n ${AN} ];then
  94. echo "没有变量AN,无法执行后续操作,请确认输入了AN参数"
  95. exit 1
  96. fi
  97.  
  98. echo "结果为:${AN} is a good ${BN}"
  99.  
  100. [root@bz3aomsmsap1002 mnt]# sh test.sh
  101. 结果为:ru is a good sadf

$(( ))、$( )、${ }的区别

  1. ===================================================================
  2. 一、$( ) ` ` (反引号)
  3. bash shell中,$( ) ` `(反引号) 都是用来做命令替换用(command substitution)的。
  4. [root@bobo tmp]# echo `hostname`
  5. kevin-testserver
  6. [root@bobo tmp]# echo $(hostname)
  7. kevin-testserver
  8.  
  9. 比如查看上一星期天的日期
  10. [root@bobo tmp]# echo the last sunday is $(date -d "last sunday" +%Y-%m-%d)[/code]
  11. the last sunday is 2019-10-27[/code]
  12.  
  13. ===================================================================
  14. 二、${ } 用来作变量替换。
  15. 一般情况下,$var ${var} 并没有什么不一样。但是用${ }会比较精确的界定变量名称的范围。
  16. 例如下面的例子,原本是打算先将$A的结果替换出来,然后再补一个B字母于其后。
  17. 如果使用$AB打印结果就为空,但是使用${A}B打印就不一样了。
  18. [root@bobo tmp]# A=B
  19. [root@bobo tmp]# echo $AB
  20.  
  21. [root@bobo tmp]# echo ${A}B
  22. BB
  23. [root@bobo tmp]#
  24.  
  25. bash中。${ }功能是十分强大的,不仅仅是用来界定变量名称,
  26. --------------------------------------
  27. 1${}可以灵活地用来截图变量中的字符串
  28. 具体可以参考:https://www.cnblogs.com/kevingrace/p/8868262.html
  29.  
  30. 例如:var="http://www.kevin.com/shibo/anhuigrace"
  31. 我们可以用 ${ } 分别替换获得不同的值:
  32. ${var#*/}:拿掉第一条/及其左边的字符串:/www.kevin.com/shibo/anhuigrace
  33. ${var##*/}:拿掉最后一条/及其左边的字符串:anhuigrace
  34. ${var#*.}:拿掉第一个.及其左边的字符串:kevin.com/shibo/anhuigrace
  35. ${var##*.}:拿掉最后一个.及其左边的字符串:com/shibo/anhuigrace
  36. ${var%/*}:拿掉最后一条/及其右边的字符串:http://www.kevin.com/shibo
  37. ${var%%/*}:拿掉第一条/及其右边的字符串:http:
  38. ${var%.*}:拿掉最后一个.及其右边的字符串:http://www.kevin
  39. ${var%%.*}:拿掉第一个.及其右边的字符串:http://www
  40.  
  41. 记忆的方法为:
  42. # 是去掉左边(在键盘上 # 在 $ 之左边)
  43. % 是去掉右边(在键盘上 % 在 $ 之右边)
  44. 单一符号是最小匹配﹔
  45. 两个符号是最大匹配。
  46.  
  47. --------------------------------------
  48. 2)${}可以对变量值里的字符串作替换
  49. ${file/dir/path}:将第一个 dir提换为path:
  50. ${file//dir/path}:将全部dir提换为path:
  51.  
  52. 示例:
  53. [root@bobo tmp]# cat test.sh
  54. #!/bin/bash
  55.  
  56. var="/data/web/kevin/www/web/ui/web/list"
  57.  
  58. echo "${var}"
  59. echo "${var/web/shi}"
  60. echo "${var//web/shi}"
  61. [root@bobo tmp]# sh test.sh
  62. /data/web/kevin/www/web/ui/web/list
  63. /data/shi/kevin/www/web/ui/web/list
  64. /data/shi/kevin/www/shi/ui/shi/list
  65.  
  66. --------------------------------------
  67. 3) 利用 ${ } 还可针对不同的变量状态赋值(没设定、空值、非空值)
  68. ${var-kevin.txt}:假如$var没有设定,则使用kevin.txt作传回值。(空值及非空值时不作处理)
  69. ${var:-kevin.txt}:假如$var没有设定或为空值,则使用kevin.txt作传回值。(非空值时不作处理)
  70. ${var+kevin.txt}:假如$var设为空值或非空值,均使用kevin.txt作传回值。(没设定时不作处理)
  71. ${var:+kevin.txt}:若$var为非空值,则使用kevin.txt作传回值。(没设定及空值时不作处理)
  72. ${var=kevin.txt}:若$var没设定,则使用kevin.txt作传回值,同时将$var赋值为kevin.txt。(空值及非空值时不作处理)
  73. ${var:=kevin.txt}:若$var没设定或为空值,则使用kevin.txt作传回值,同时将$var赋值为kevin.txt。(非空值时不作处理)
  74. ${var?kevin.txt}:若$var没设定,则将kevin.txt输出至STDERR。(空值及非空值时不作处理)
  75. ${var:?kevin.txt}:若$var没设定或为空值,则将kevin.txt输出至STDERR。(非空值时不作处理)
  76.  
  77. 示例:
  78. [root@bobo tmp]# cat test.sh
  79. #!/bin/bash
  80.  
  81. #var="/data/web/kevin/www/web/ui/web/list"
  82.  
  83. echo "${var}"
  84. echo "${var-my.txt}"
  85. echo "${var:-my.txt}"
  86. echo "${var+my.txt}"
  87. echo "${var:+my.txt}"
  88. echo "${var=my.txt}"
  89. echo "${var:=my.txt}"
  90. echo "${var?my.txt}"
  91. echo "${var:?my.txt}"
  92.  
  93. [root@bobo tmp]# sh test.sh
  94.  
  95. my.txt
  96. my.txt
  97.  
  98. my.txt
  99. my.txt
  100. my.txt
  101. my.txt
  102.  
  103. 修改下脚本
  104. [root@bobo tmp]# cat test.sh
  105. #!/bin/bash
  106.  
  107. var="/data/web/kevin/www/web/ui/web/list"
  108.  
  109. echo "${var}"
  110. echo "${var-my.txt}"
  111. echo "${var:-my.txt}"
  112. echo "${var+my.txt}"
  113. echo "${var:+my.txt}"
  114. echo "${var=my.txt}"
  115. echo "${var:=my.txt}"
  116. echo "${var?my.txt}"
  117. echo "${var:?my.txt}"
  118.  
  119. [root@bobo tmp]# sh test.sh
  120. /data/web/kevin/www/web/ui/web/list
  121. /data/web/kevin/www/web/ui/web/list
  122. /data/web/kevin/www/web/ui/web/list
  123. my.txt
  124. my.txt
  125. /data/web/kevin/www/web/ui/web/list
  126. /data/web/kevin/www/web/ui/web/list
  127. /data/web/kevin/www/web/ui/web/list
  128. /data/web/kevin/www/web/ui/web/list
  129.  
  130. 需要注意的是:
  131. 以上理解一定要分清楚unset 与 null 及 non-null 这三种赋值状态。一般而言:
  132. : 与 null 有关;
  133. 若不带 : 的话, 则 null 不受影响,;
  134. 若带 : 的话,则连 null 也受影响.
  135.  
  136. --------------------------------------
  137. 4)${#var} 可计算出变量值的长度
  138. [root@bobo tmp]# cat test.sh
  139. #!/bin/bash
  140.  
  141. var="/data/web/kevin/www/web/ui/web/list"
  142.  
  143. echo "${#var}"
  144.  
  145. [root@bobo tmp]# sh test.sh
  146. 35
  147.  
  148. 这里就引申出shell中的数组的概念了,数组的使用可以参考:https://www.cnblogs.com/kevingrace/p/5761975.html
  149.  
  150. 这里简单说明下:
  151. 一般而言,var="haha hehe heihei houhou" 这样的变量只是将${var}替换为一个单一的字符串,
  152. [root@bobo tmp]# var="haha hehe heihei houhou"
  153. You have mail in /var/spool/mail/root
  154. [root@bobo tmp]# echo ${var}
  155. haha hehe heihei houhou
  156.  
  157. 如果改为 var=(haha hehe heihei houhou) ,则是将${var}定义为组数。
  158. [root@bobo tmp]# var=(haha hehe heihei houhou)
  159.  
  160. bash 的组数替换方法可参考如下方法:
  161. ${var[@]} 或 ${var[*]} 可得到 haha hehe heihei houhou (全部组数)
  162. ${var[0]} 可得到 haha (第一个组数),${var[1]} 则为第二个组数…
  163. ${#var[@]} 或 ${#var[*]} 可得到 4 (全部组数数量)
  164. ${#var[0]} 可得到4(即第一个组数(haha)的长度),${#var[3]} 可得到6(第四个组数(houhou)的长度)
  165. var[3]=xyz 则是将第四个组数重新定义为xyz …
  166.  
  167. [root@bobo tmp]# echo ${var[@]}
  168. haha hehe heihei houhou
  169. [root@bobo tmp]# echo ${var[*]}
  170. haha hehe heihei houhou
  171. [root@bobo tmp]# echo ${var[0]}
  172. haha
  173. [root@bobo tmp]# echo ${var[1]}
  174. hehe
  175. [root@bobo tmp]# echo ${#var[@]}
  176. 4
  177. [root@bobo tmp]# echo ${#var[*]}
  178. 4
  179. [root@bobo tmp]# echo ${#var[0]}
  180. 4
  181. [root@bobo tmp]# echo ${#var[3]}
  182. 6
  183. [root@bobo tmp]# var[3]=xyz
  184. [root@bobo tmp]# echo ${var[@]}
  185. haha hehe heihei xyz
  186.  
  187. ===================================================================
  188. 三、 $(( )) 的用途:
  189. 1)$(( ))是用来作整数运算的。
  190. + - * / :分别为 "加、减、乘、除"。
  191. % :余数运算
  192. & | ^ !:分别为 "AND、OR、XOR、NOT" 运算。
  193.  
  194. [root@bobo tmp]# a=5; b=7; c=2
  195. [root@bobo tmp]# echo $(( a+b*c ))
  196. 19
  197. [root@bobo tmp]# echo $(( (a+b)/c ))
  198. 6
  199. [root@bobo tmp]# echo $(( (a*b)%c))
  200. 1
  201.  
  202. 在 $(( )) 中的变量名称,可于其前面加 $ 符号来替换,也可以不用,如:
  203. [root@bobo tmp]# echo $(( $a + $b * $c))
  204. 19
  205. [root@bobo tmp]# echo $(( ($a * $b) % $c))
  206. 1

Shell 脚本中诸如查看目录大小并排序等技巧

  1. =====================================================================
  2. 查看目录下的文件大小并排序
  3.  
  4. 1. 查看/data目录下空间大小排在前10位的文件
  5. # du -sh /data/* | sort -nr | head -10
  6.  
  7. 查看目录下所有文件的大小并按照大小排序
  8. # du -sh * | sort -rh
  9.  
  10. 2. 查看/data目录下空间大小排在前10位的目录(单位为G),并且只是在/data当前目录下查看,不轮询(用到参数"-maxdepth 1"
  11. # find /data/* -maxdepth 1 -type d -exec /usr/bin/du -sh {} \;|grep '[0-9]G'|sort -rh|head -5
  12.  
  13. [bxapp@bz6aomdepap1001 ~]$ find /data/ftp/ONLINE/* -maxdepth 1 -type d -exec /usr/bin/du -sh {} \;|grep '[0-9]G'|sort -rh|head -5
  14. 64G /data/ftp/ONLINE/CCS
  15. 13G /data/ftp/ONLINE/MPB
  16. 11G /data/ftp/ONLINE/ICS
  17. 9.5G /data/ftp/ONLINE/mysql
  18. 9.0G /data/ftp/ONLINE/EOB
  19.  
  20. =====================================================================
  21. Shell中求字符串中单词的个数的几种方法
  22.  
  23. 方法一:
  24. [root@VM_16_9_centos tmp]# echo 'wang shi kevin ruo bao' | wc -w
  25. 5
  26.  
  27. 方法二:
  28. [root@VM_16_9_centos tmp]# echo 'wang shi kevin ruo bao' | awk '{print NF}'
  29. 5
  30.  
  31. 方法三:
  32. [root@VM_16_9_centos tmp]# s='wang shi kevin ruo bao'
  33. [root@VM_16_9_centos tmp]# set ${s}
  34. [root@VM_16_9_centos tmp]# echo $#
  35. 5
  36.  
  37. 方法四:
  38. [root@VM_16_9_centos tmp]# s='wang shi kevin ruo bao'
  39. [root@VM_16_9_centos tmp]# a=($s)
  40. [root@VM_16_9_centos tmp]# echo ${#a[@]}
  41. 5
  42.  
  43. 方法五:
  44. [root@VM_16_9_centos tmp]# s='wang shi kevin ruo bao'
  45. [root@VM_16_9_centos tmp]# echo $s | tr ' ' '\n' | wc -l
  46. 5
  47.  
  48. =====================================================================
  49. linux 中wc 用法小结
  50. wc命令用于统计给定文件中的字节数、字数、行数。
  51. 如果没有给出文件名,则从标准输入读取。
  52. wc同时也给出所有指定文件的总统计数。字是由空格字符区分开的最大字符串。
  53.  
  54. wc命令各选项含义如下:
  55. - c 统计字节数
  56. - l 统计行数
  57. - w 统计字数
  58.  
  59. 1. 统计行数:
  60. # wc -l file
  61.  
  62. 2. 如果需要将stdin作为输入,使用下列命令:
  63. #cat file | wc -l
  64.  
  65. 3. 统计单词数:
  66. # wc -w file
  67. # cat file | wc -w
  68.  
  69. 4. 统计字符数:
  70. # wc -c file
  71. # cat file | wc -c
  72.  
  73. 可以按照下面的方法统计文本中的字符数:
  74. -n用于避免echo添加额外的换行符。
  75. [root@VM_16_9_centos tmp]# echo "CCS"|wc -c
  76. 4
  77. [root@VM_16_9_centos tmp]# echo -n "CCS"|wc -c
  78. 3
  79. 4
  80.  
  81. 5. 当不使用任何选项执行wc时:
  82. # wc file
  83. 1435 15763 112200
  84. 它会分别打印出文件的行数、单词数和字符数。
  85.  
  86. 6. 使用-L选项打印出文件中最长一行的长度:
  87. # wc file -L
  88. 205
  89.  
  90. =====================================================================
  91. shell求两个数相除后的百分比
  92.  
  93. [root@VM_16_9_centos tmp]#
  94. [root@VM_16_9_centos tmp]# cat test.sh
  95. #!/bin/bash
  96. NUM1=78
  97. NUM2=345
  98.  
  99. Percent_1=$(printf "%d%%" $((${NUM1}*100/${NUM2})))
  100. #或者
  101.  
  102. #保留1位小数,四舍五入
  103. Percent_2=`awk 'BEGIN{printf "%.1f%%\n",('${NUM1}'/'${NUM2}')*100}'`
  104.  
  105. #保留3位小数,四舍五入
  106. Percent_3=`awk 'BEGIN{printf "%.3f%%\n",('${NUM1}'/'${NUM2}')*100}'`
  107.  
  108. echo $Percent_1
  109. echo $Percent_2
  110. echo $Percent_3
  111. [root@VM_16_9_centos tmp]# sh test.sh
  112. 22%
  113. 22.6%
  114. 22.609%

shell脚本之特殊符号总结性梳理的更多相关文章

  1. 【转】70个经典的 Shell 脚本面试问题

    我们为你的面试准备选择了 70 个你可能遇到的 shell 脚面问题及解答.了解脚本或至少知道基础知识对系统管理员来说至关重要,它也有助于你在工作环境中自动完成很多任务.在过去的几年里,我们注意到所有 ...

  2. Shell 脚本面试问题大全

    我们为你的面试准备选择了 70 个你可能遇到的 shell 脚本面试问题及解答.了解脚本或至少知道基础知识对系统管理员来说至关重要,它也有助于你在工作环境中自动完成很多任务.在过去的几年里,我们注意到 ...

  3. 70个经典的 Shell 脚本面试问题

    转载自:http://www.imooc.com/article/1131 1) 如何向脚本传递参数 ? ./script argument 例子: 显示文件名称脚本 ./show.sh file1. ...

  4. Linux shell脚本学习(一)

    一.shell脚本简介 shell脚本是用shell脚本语法将shell命令组织起来形成的文件形式.Shell脚本与Windows/Dos 下的批处理相似,主要为了将大量命令通过一个纯文本文件一次执行 ...

  5. Linux Shell编程第1章——Shell脚本编程概述

    目录 Linux和Shell简介 Linux是一套可免费使用和自由传播的类UNIX操作系统.Shell是一种具备特殊功能的程序,它提供了用户与内核进行交互操作的一种接口.它接收用户输入的命令,并把它送 ...

  6. linux之shell脚本

    1) 如何向脚本传递参数 ? ./script argument 例子: 显示文件名称脚本 ? 1 2 3 4 ./show.sh file1.txt cat show.sh #!/bin/bash ...

  7. shell 脚本关键字&符号

    shell概念 "shell"既是一种解释型编程语言,也是一个这种编程语言的解释器的名字 shell是解释型语言,就是解释器会一条一条的翻译每一条语句并执行,对比之下,C语言是编译 ...

  8. shell脚本中的特殊符号

    1.{} 大括号:用法一:通配符扩展eg: ls my_{finger,toe}s这条命令相当于如下命令的组合:ls my_fingers my_toeseg: mkdir {userA,userB, ...

  9. shell脚本中一些特殊符号

    在shell中常用的特殊符号罗列如下: # ;   ;; . , / \\ 'string'| !   $   ${}   $? $$   $* \"string\"* **   ...

随机推荐

  1. java调用python的惨痛史(无法获取环境变量)

    环境:java,was,python2.6,红帽linux,oracle,python用cx_Oracle        事情是这样的,有个需求,需要对数据库进行处理,简单说就是把数据取出来,用pyt ...

  2. January 16th, 2018 Week 03rd Tuesday

    Accept who you are, and revel in it. 接受真实的自己并乐在其中. Try to accept youself and try to love yourself mo ...

  3. npm包开发(whale-makelink)

    whale-makelink是一个npm工具,是强业务的工具,可以将当前工程目录下的项目文件夹,在README中生成项目的链接地址.Demo. 一.npm init 使用npm init生成packa ...

  4. Jquery 中 ajaxSubmit使用讲解

    最近在使用ajaxForm,随便把使用方法记下下来,以便以后回顾. 1 ,引入依赖脚本 <script type="text/javascript" src="/j ...

  5. 【BZOJ4259】残缺的字符串

    [BZOJ4259]残缺的字符串 Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时, ...

  6. 【九校3D2T3】世界第一的猛汉王

    [问题描述] 卡普地公司举办了「世界第一的猛汉王」全球大会,来自世界各地的猛汉为了争夺「猛汉王」的名号前来一决高下.现在举行的是弓箭组选拔赛.卡普地公司为比赛新建了一张PVP地图——「猛汉竞技场」.有 ...

  7. Django之Form进阶

    s6day76 内容回顾: Form组件:  - 类  继承Form  - 字段  字段  - 实例化  - is_valid()  - cleaned_data  - errors Form 组件: ...

  8. sed命令替换字符包含斜杠\,引号的处理方法

    在字符替换中,可能会遇见引号,“/”等的替换,这时应该注意,sed的命令原型是: sed -i  "s/oldstring/goalstring/g" file 如果一个路径是da ...

  9. QT插件+ROS 3 导入现有ROS包

    http://blog.csdn.net/u013453604/article/details/52167213#t5

  10. python开发技巧---列表、字典、集合值的过滤

    主要学习列表,字典,集合表达式的应用: 列表的解析式: 生成一个随机列表: In [4]: datalist = [randint(-10,10) for _ in range(10)] In [5] ...