Linux常用命令--各种符号

摘要

  • 文本介绍linux编程中会用到的各种符号的使用方法

  • 特殊变量: 0、?、*、@、#、_、$!

  • &和&&、|和||

  • 命令替换: $( ) 与 ``

  • 整数运算: $(( )) 与 $[ ]

  • 条件判断: (( ))、[ ]与[[ ]]

  • 变量引用: $ 与 ${ }

  • 本文基于CentOS8(x86_64)

特殊变量: $0、$?、$*、$@、$#、$$、$!

  • $0 : 当前脚本的文件名(间接运行时还包括绝对路径)。

  • $n : 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1 。

  • $# : 传递给脚本或函数的参数个数。

  • $* : 传递给脚本或函数的所有参数。

  • $@ : 传递给脚本或函数的所有参数。被双引号 "$@" 包含时,与 "$*" 不同,下面将会讲到。

  • $? : 上个命令的退出状态(0:success 非0:error),或函数的返回值。这个非常有用,常用语法是:if [ $? -eq 0 ]

  • $$ : 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。

  • $_ : 上一个命令的最后一个参数

  • $! : 后台运行的最后一个进程的 ID 号

小贴士
$?常见非0状态码:

1
2
3
4
5
6
1:通用错误
2:命令不正确
126:命令调用的程序无法执行(权限问题)
127:命令未找到
128:无效的参数
130:命令被 Ctrl+C 中断

$*$@ 都表示传递给函数或脚本的所有参数,不被双引号 "" 包含时,都以独立个体"$1" "$2" … "$n" 的形式输出所有参数。
但是当它们被双引号 "" 包含时,"$*"会将所有的参数作为一个整体输出,"$@"依旧会以独立个体"$1" "$2" … "$n" 的形式输出所有参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# $*
for i in $*
do
echo $i
done
# sh test.sh 1 2 3 4,此时输出
1
2
3
4

# "$*"
for i in "$*"
do
echo $i
done
# sh test.sh 1 2 3 4,此时输出
1 2 3 4

# $@
for i in $@
do
echo $i
done
# sh test.sh 1 2 3 4,此时输出
1
2
3
4

# "$@"
for i in "$@"
do
echo $i
done
# sh test.sh 1 2 3 4,此时输出
1
2
3
4

获取参数数量:

1
paramSize=${#@}

&&&|||

  • & 表示任务在后台执行,如要在后台运行redis-server,则有 redis-server &

  • && 表示前一条命令执行成功时,才执行后一条命令 ,如 make && make install

  • | 表示管道,上一条命令的输出,作为下一条命令参数,如 cat text.txt | wc -l

  • || 表示上一条命令执行失败后,才执行下一条命令,如 grep "success" run.log || echo "fail"

命令替换: $( ) 与 ``

  • $( ) 与 `` 都是用来作命令替换的,优先执行括号或者反引号中的命令,并将结果替换出来组成新的命令

1
2
3
4
5
6
7
8
# 以下命令效果相同
echo today is `date "+%Y-%m-%d"`
echo today is $(date "+%Y-%m-%d")

today=`date "+%Y-%m-%d"`
echo $today
today=$(date "+%Y-%m-%d")
echo $today
  • 推荐使用$( ),因为在多层次的复合替换中,内部的`` 必须要进行转义,而$( )比较直观

1
2
3
4
#  cmd3 `cmd2 \`cmd1\``
sh echo.sh "`echo today is \`date "+%Y-%m-%d"\``"
# cmd3 $(cmd2 $(cmd1))
sh echo.sh "$(echo today is $(date "+%Y-%m-%d"))"

整数运算: $(( ))$[ ]

  • $(( ))用于执行整数计算,等价于$[ ]

1
2
3
4
5
echo $(( 3+5 ))
echo $[ 3+5 ]

echo $(( (3+5)*4/2 ))
echo $[ (3+5)*4/2 ]

条件判断: (( ))[ ][[ ]]

  • 在使用ifwhile等语句时,需要进行条件判断,(( ))[ ][[ ]]都可以用来进行条件判断,那么他们之间有什么区别吗?

    • [ ]test命令的另一种形式,例如 test a == b 等同于 [ a == b ],注意 [ 后和 ] 前都需要有空格,并且==两边也都要有空格
    1
    2
    3
    test 'hello' != 'world' ==>  [ 'hello' != 'world' ]
    test ! -e test.sh ==> [ ! -e test.sh ]
    test $i -lt 5 ==> [ $i -lt 5 ]
    • [[ ]][ ]的增强版,其在如下几个方面进行了增强:
      • 1.在[[ ]]中使用>< 进行数值比较时不需要转义,但是不支持>=<=
      • 2.支持&&||
      1
      2
      3
      4
      # 以下三种作用相同
      [[ $a > 3 && $a != 10 ]]
      [ $a > 3 -a $a != 10 ]
      [ $a > 3 ] && [ $a != 10 ]
      • 3.[[ ]]在比较字符串时支持正则匹配和通配符匹配
      1
      2
      3
      4
      5
      6
      7
      8
      9
      # 通配符匹配
      a="linux"
      [[ $a == l?nu? ]] # 0
      [[ $a != li* ]] # 1

      # 正则匹配 `=~`
      a="linux"
      [[ $a =~ ^li ]]
      [[ $a =~ ^li[abn]ux ]]
    • (( )) 用于条件判断时只能进行数值比较,运算符不需要转义,而且不支持-lt-gt等等
      1
      (( $i <= 5 ))

    小贴士
    (( ))除了用于条件判断外,还有三种用法:
    1.与$结合使用进行数学运算 : $(( ))
    2.在for循环命令中控制循环 : for((i=1;i<10;i++))
    3.改变变量的值,且变量前不需要$ : ((i++))

  • 推荐在进行条件判断时使用[[ ]],运算符不需要转义,而且支持正则

变量引用: $${ }

  • $${ }都是用来引用变量的,${ }通常用于划定变量名的边界,当执行 echo "$aa"的时候系统会打印变量$aa的值,当执行echo "${a}a"时打印的是${a}和字母a,如果不需要为变量名划分边界的话,$a${a}是完全相等的。

1
2
3
today=`date "+%Y-%m-%d"`
echo $today
echo ${today}_now
  • ${ }还有一个重要的功能,就是文本处理:

    • 1.获取字符串长度
    1
    2
    str='hello'
    echo ${#str} # 5
    • 2.字符串切片${a:b:c}: 将字符串变量a从第b个位置开始向后截取c个字符,b是指下标,下标从0开始,c可以不指定,表示截取到字符串末尾
    1
    2
    3
    4
    5
    6
    7
    8
    a='hello world!'
    echo ${a:0:5} # hello
    # 不指定c,表示从第6个字符开始截取到字符串末尾
    echo ${a:6} # world!
    # 截取从倒数第一个字符开始到字符串末尾的字符
    echo ${a:(-1)} # !
    # 截取从倒数第 6 个字符后的 5 个字符
    echo ${a:(-6):5} # world
    • 3.替换字符串${a/b/c}: 将变量a中的b全部替换为c,开头一个正斜杠为只匹配第一个字符串,两个正斜杠为匹配所有字符。
    1
    2
    3
    4
    5
    6
    7
    a='hello hello world'
    echo "${a/hello/hi}" # hi hello world
    echo "${a//hello/hi}" # hi hi world
    # 支持正则
    str=123abc
    echo ${str//[^0-9]/} # 123,将非数字替换为空
    echo ${str//[0-9]/} # abc,将数字替换为空
    • 4.字符串截取
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    # 格式:
    # 删除匹配前缀
    ${parameter#word}
    ${parameter##word}
    # 删除匹配后缀
    ${parameter%word}
    ${parameter%%word}
    # 去掉左边,#最短匹配模式,##最长匹配模式。
    % 去掉右边,%最短匹配模式,%%最长匹配模式。

    # 示例
    URL="http://www.baidu.com/baike/user.html"
    # 匹配http://,以//为分隔符截取出右边字符串
    echo ${URL#*//} # www.baidu.com/baike/user.html

    # 以/为分隔符截取右边字符串,##表示尽可能多的删除,保留最少内容
    echo ${URL##*/} # user.html
    echo ${URL#*/} # /www.baidu.com/baike/user.html

    # 以/为分隔符截取左边字符串,%%表示尽可能多的删除,即保留最少内容
    echo ${URL%%/*} # http:
    echo ${URL%/*} # http://www.baidu.com/baike
    • 5.变量状态赋值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    # 格式
    ${VAR:-string} # 如果 VAR 变量为空则返回 string
    ${VAR:+string} # 如果 VAR 变量不为空则返回 string
    ${VAR:=string} # 如果 VAR 变量为空则重新赋值 VAR 变量值为 string
    ${VAR:?string} # 如果 VAR 变量为空则将 string 输出到 stderr

    # 示例
    # 如果变量为空就返回 hello world!
    VAR=
    echo ${VAR:-'hello world!'} # hello world!
    echo $VAR # 空

    # 如果变量不为空就返回 hello world!
    VAR="hello"
    echo ${VAR:+'hello world!'} # hello world!
    echo $VAR # hello

    #如果变量为空就重新赋值:
    VAR=
    echo ${VAR:=hello} # hello
    echo $VAR # hello

    # 如果变量为空就将信息输出 stderr
    VAR=
    echo ${VAR:?value is null} # -bash: VAR: value is null