shell
基本语法
1 解释器
#! /bin/sh
#!/bin/bash
#!/usr/bin/env bash
2 注释
注释可以说明你的代码是什么作⽤,以及为什么这样写。
shell 语法中,注释是特殊的语句,会被 shell 解释器忽略。
单⾏注释 - 以 # 开头,到⾏尾结束。
多⾏注释 - 以 :<<EOF 开头,到 EOF 结束。
# echo '这是单⾏注释'
########## 这是分割线 ##########
:<<EOF
echo '这是多⾏注释'
echo '这是多⾏注释'
echo '这是多⾏注释'
EOF
3 echo
echo ⽤于字符串的输出。
输出普通字符串:
[root@i-m60lx3hh ~]# echo "hello, world"
hello, world
[root@i-m60lx3hh ~]# echo "hello, \"xu\""
hello, "xu"
输出含变量的字符串:
[root@i-m60lx3hh ~]# name=xu
[root@i-m60lx3hh ~]# echo "hello, \"${name}\""
hello, "xu"
输出含换⾏符的字符串:
# 输出含换⾏符的字符串
echo "YES\nNO"
# Output: YES\nNO
echo -e "YES\nNO" # -e 开启转义
# Output:
# YES
# NO
输出含不换⾏符的字符串:
echo "YES"
echo "NO"
# Output:
# YES
# NO
echo -e "YES\c" # -e 开启转义 \c 不换⾏
echo "NO"
# Output:
# YESNO
输出重定向⾄⽂件
echo "test" > test.txt
输出执⾏结果
echo `pwd`
# Output:(当前⽬录路径)
4 printf
printf ⽤于格式化输出字符串。
默认,printf 不会像 echo ⼀样⾃动添加换⾏符,如果需要换⾏可以⼿动添加 \n 。
printf 的转义符
\a 警告字符,通常为 ASCII 的 BEL 字符
\b 后退
\c
抑制(不显示)输出结果中任何结尾的换⾏字符(只在%b 格式指示符控制下的参数字符串中有
效),⽽且,任何留在参数⾥的字符、任何接下来的参数以及任何留在格式字符串中的字符,都
被忽略
\f 换⻚(formfeed)
\n 换⾏
\r 回⻋(Carriage return)
\t ⽔平制表符
\v 垂直制表符
\\ ⼀个字⾯上的反斜杠字符
\ddd 表示 1 到 3 位数⼋进制值的字符。仅在格式字符串中有效
\0ddd 表示 1 到 3 位的⼋进制值字符
# 单引号
printf '%d %s\n' 1 "abc"
# Output:1 abc
# 双引号
printf "%d %s\n" 1 "abc"
# Output:1 abc
# ⽆引号
printf %s abcdef
# Output: abcdef(并不会换⾏)
# 格式只指定了⼀个参数,但多出的参数仍然会按照该格式输出
printf "%s\n" abc def
# Output:
# abc
# def
printf "%s %s %s\n" a b c d e f g h i j
# Output:
# a b c
# d e f
# g h i
# j
# 如果没有参数,那么 %s ⽤ NULL 代替,%d ⽤ 0 代替
printf "%s and %d \n"
# Output:
# and 0
# 格式化输出
[root@i-m60lx3hh ~]# printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
[root@i-m60lx3hh ~]# printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
[root@i-m60lx3hh ~]# printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
[root@i-m60lx3hh ~]# printf "%-10s %-8s %-4.2f\n" 郭芙 ⼥ 47.9876
姓名 性别 体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 ⼥ 47.99
变量
跟许多程序设计语⾔⼀样,你可以在 bash 中创建变量。
Bash 中没有数据类型,bash 中的变量可以保存⼀个数字、⼀个字符、⼀个字符串等等。同时⽆需提前声明变量,给变量赋值会直接创建变量。
1 变量命名原则
命名只能使⽤英⽂字⺟,数字和下划线,⾸个字符不能以数字开头。
中间不能有空格,可以使⽤下划线(_)。
不能使⽤标点符号。
不能使⽤ bash ⾥的关键字(可⽤ help 命令查看保留关键字)。
2 声明变量
访问变量的语法形式为: ${var} 和 $var 。
变量名外⾯的花括号是可选的,加不加都⾏,加花括号是为了帮助解释器识别变量的边界,所以推荐加花括号。
[root@i-m60lx3hh ~]# world="world"
[root@i-m60lx3hh ~]# echo ${world}
world
3 只读变量
使⽤ readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
[root@i-m60lx3hh ~]# rword="hello"
[root@i-m60lx3hh ~]# echo ${rword}
hello
[root@i-m60lx3hh ~]# readonly rword
[root@i-m60lx3hh ~]# rword="bye"
-bash: rword: readonly variable
[root@i-m60lx3hh ~]# #rword="bye"
[root@i-m60lx3hh ~]#
[root@i-m60lx3hh ~]# echo ${rword}
hello
4 删除变量
使⽤ unset 命令可以删除变量。变量被删除后不能再次使⽤。unset 命令不能删除只读变量。
dword="hello" # 声明变量
echo ${dword} # 输出变量值
# Output: hello
unset dword # 删除变量
echo ${dword}
# Output: (空)
5 变量作⽤域
局部变量 - 局部变量是仅在某个脚本内部有效的变量。它们不能被其他的程序和脚本访问。
环境变量 - 环境变量是对当前 shell 会话内所有的程序或脚本都可⻅的变量。创建它们跟创建局部变量类似,但使⽤的是 export 关键字,shell 脚本也可以定义环境变量。
常⻅的系统环境变量:
$HOME 当前⽤户的⽤户⽬录
$SHELL 默认 Shell
$LANG 默认语⾔
$PATH ⽤分号分隔的⽬录列表,shell 会到这些⽬录中查找命令
$HOSTNAME 主机名
$PWD 当前⼯作⽬录
$RANDOM 0 到 32767 之间的整数
$UID 数值类型,当前⽤户的⽤户 ID
$PS1 主要系统输⼊提示符
$PS2 次要系统输⼊提示符
注意系统环境变量加载顺序:执⾏顺序:/etc/profile -> ~/.bash_profile -> ~/.bashrc -> /etc/bashrc -> ~/.bash_logout
6 位置变量
位置变量指的是函数或脚本后跟的第n 个参数。
$1-$n,需要注意的是从第 10 个开始要⽤花括号调⽤,例如${10} shift 可对位置变量控制,例如:
#!/bin/bash
echo "1: $1"
echo "2: $2"
echo "2: $3"
#!/bin/bash
echo "1: $1"
shift
echo "2: $2"
shift
echo "3: $3"
# bash positi_par_2.sh a b c 1: e
1: a
2: c
3: e
每执⾏⼀次 shift 命令,位置变量个数就会减⼀,⽽变量值则提前⼀位。shift n,可设置向前移动n 位。
7 特殊变量
$0 脚本⾃身名字
$? 返回上⼀条命令是否执⾏成功,0 为执⾏成功,⾮ 0 则为执⾏失败
$# 位置参数总数
$* 所有的位置参数被看做⼀个字符串
$@ 每个位置参数被看做独⽴的字符串
$$ 当前进程 PID
$! 上⼀条运⾏后台进程的 PID
#!/bin/bash
#$0 返回脚本名称
echo $0
# $?: 上个命令的退出状态,0 表示成功,⾮零值表示失败
echo "Executing ls command"
ls
echo "Exit status of ls command: $?"
# $#: 命令⾏参数的个数
if [ $# -gt 0 ]; then
echo "Number of input arguments: $#"
echo "Input arguments: $@"
else
echo "No input arguments provided"
fi
# $*: 所有命令⾏参数作为单个字符串
echo "Outputting all input arguments as single string: $*"
# $@: 所有命令⾏参数作为单独的字符串
echo "Outputting all input arguments as separate strings:"
for arg in "$@"; do
echo "$arg"
done
# $$: 当前进程的 PID
echo "PID of current process: $$"
# $!: 最后⼀次运⾏的后台进程的 PID
echo "Starting sleep command in background"
sleep 5 &
echo "PID of sleep command: $!"
注意事项 $* $@区别
『示例源码』
#!/usr/bin/env bash
################### 声明变量 ###################
name="world"
echo "hello ${name}"
# Output: hello world
################### 输出变量 ###################
folder=$(pwd)
echo "current path: ${folder}"
################### 只读变量 ###################
rword="hello"
echo ${rword}
# Output: hello
readonly rword
# rword="bye" # 如果放开注释,执⾏时会报错
################### 删除变量 ###################
dword="hello" # 声明变量
echo ${dword} # 输出变量值
# Output: hello
unset dword # 删除变量
echo ${dword}
# Output: (空)
################### 系统变量 ###################
echo "UID:$UID"
echo LOGNAME:$LOGNAME
echo User:$USER
echo HOME:$HOME
echo PATH:$PATH
echo HOSTNAME:$HOSTNAME
echo SHELL:$SHELL
echo LANG:$LANG
################### 随机数 ###################
# ⽣成 1 到 10 之间的随机数
echo $(( $RANDOM % 10 + 1 ))
# ⽣成 1 到 100 之间的随机数
echo $(( $RANDOM % 100 + 1 ))
################### ⾃定义变量 ###################
days=10
user="admin"
echo "$user logged in $days days age"
days=5
user="root"
echo "$user logged in $days days age"
# Output:
# admin logged in 10 days age
# root logged in 5 days age
################### 从变量读取列表 ###################
colors="Red Yellow Blue"
colors=$colors" White Black"
for color in $colors
do
echo " $color"
done
字符串
1 单引号和双引号
shell 字符串可以⽤单引号 '' ,也可以⽤双引号 “” ,也可以不⽤引号。
单引号的特点
单引号⾥不识别变量
单引号⾥不能出现单独的单引号(使⽤转义符也不⾏),但可成对出现,作为字符串拼接使⽤。
双引号的特点
双引号⾥识别变量
双引号⾥可以出现转义字符
#!/bin/bash
name='xu'
echo 'Hello, $name'
# Output: Hello, $name
name='xu'
echo "Hello, $name"
# Output: Hello, Wing
echo 'I'\''m a programmer'
# Output: I'm a programmer
echo "I'm a programmer"
# Output: I'm a programmer
echo "some text" # Output: some text
echo 'some text' # Output: some text
echo "the date is $(date)"
# Output: the date is Wed May 12 11:47:02 CST 2021
echo 'the date is $(date)'
# Output: the date is $(date)
在上述脚本中,展示了单引号和双引号之间的区别,主要包括以下⼏点:
使⽤单引号时,其中的变量不会被展开。例如,在示例1中,由于使⽤了单引号,因此 $name 不会被展开,
输出的结果就是 "Hello, $name" 。
使⽤双引号时,其中的变量会被展开。例如,在示例2中,由于使⽤了双引号,因此 $name 会被展开为
John,输出的结果就是 "Hello, John" 。
使⽤单引号时,需要通过反斜杠来转义其中的特殊字符,例如示例3。
使⽤双引号时,⼀些特殊字符不需要转义,例如单引号和反斜杠,例如示例4。
使⽤双引号时,可以保留空格和制表符,例如示例5。
使⽤单引号时,可以保留其中的所有字符,包括其中的特殊字符和变量名,例如示例6。
综上所述,单引号和双引号之间存在明显的区别,需要根据具体情况和需求来选择使⽤哪种引号。
2 拼接字符串
# 使⽤单引号拼接
name1='white'
str1='hello, '${name1}''
str2='hello, ${name1}'
echo ${str1}_${str2}
# Output:
# hello, white_hello, ${name1}
# 使⽤双引号拼接
name2="black"
str3="hello, "${name2}""
str4="hello, ${name2}"
echo ${str3}_${str4}
# Output:
# hello, black_hello, black
3 获取字符串⻓度
text="12345"
echo ${#text}
# Output:
# 5
4 截取⼦字符串
text="12345"
echo ${text:2:2}
# Output:
# 34
从第 3 个字符开始,截取 2 个字符
5 从指定字符(⼦字符串)开始截取
这种截取⽅式⽆法指定字符串⻓度,只能从指定字符( ⼦字符串 )截取到字符串末尾。Shell 可以截取指定字符
(⼦字符串)右边的所有字符,也可以截取左边的所有字符。
1) 使⽤ # 号截取右边字符
使⽤ # 号可以截取指定字符(或者⼦字符串)右边的所有字符,具体格式如下:
${string#*chars}
其中,string 表示要截取的字符,chars 是指定的字符(或者⼦字符串), * 是通配符的⼀种,表示任意⻓度的字
符串。 *chars 连起来使⽤的意思是:忽略左边的所有字符,直到遇⻅ chars(chars 不会被截取)。
请看下⾯的例⼦:
url="http://www.baidu.com"
[root@i-m60lx3hh shell]# echo ${url#*c}
om
如果希望直到最后⼀个指定字符(⼦字符串)再匹配结束,那么可以使⽤ ## ,具体格式为:
${string##*chars}
url="http://www.baidu.com"
[root@i-m60lx3hh shell]# echo ${url##*w}
.baidu.com
2) 使⽤ % 截取左边字符
使⽤ % 号可以截取指定字符(或者⼦字符串)左边的所有字符,具体格式如下:
${string%chars*}
请注意 * 的位置,因为要截取 chars 左边的字符,⽽忽略 chars 右边的字符,所以 * 应该位于 chars 的右侧。其他
⽅⾯ % 和 # 的⽤法相同
url="http://www.baidu.com"
[root@i-m60lx3hh shell]# echo ${url%a*}
http://www.b
汇总:
${string:start:length} 从 string 字符串的左边第 start 个字符开始,向右截取 length 个字符。
${string:start} 从 string 字符串的左边第 start 个字符开始截取,直到最后。
${string:0-start:length} 从 string 字符串的右边第 start 个字符开始,向右截取 length 个字符。
${string:0-start} 从 string 字符串的右边第 start 个字符开始截取,直到最后。
${string#*chars} 从 string 字符串第⼀次出现 *chars 的位置开始,截取 *chars 右边的所有字符。
${string##*chars} 从 string 字符串最后⼀次出现 *chars 的位置开始,截取 *chars 右边的所有字符。
${string%*chars} 从 string 字符串第⼀次出现 *chars 的位置开始,截取 *chars 左边的所有字符。
${string%%*chars} 从 string 字符串最后⼀次出现 *chars 的位置开始,截取 *chars 左边的所有字符。
6 查找⼦字符串
#!/usr/bin/env bash
text="hello"
echo `expr index "${text}" ll`
# Execute: ./str-demo5.sh
# Output:
# 3
查找 ll ⼦字符在 hello 字符串中的起始位置。
这个命令调⽤ expr 命令来查找字符串 ${text} 中⼦串 "ll" 的第⼀次出现位置。 "${text}" ⽤双引号括起
来,表示将变量 $text 的值作为⼀个单独的参数传递给 index 函数。注意,为了避免在 $text 的值中包含空格
或其他特殊字符时出现错误,我们使⽤了双引号将 ${text} 包起来。
最后,我们使⽤ echo 命令将 index 函数的输出打印到屏幕上。为了调⽤ index 函数并将它的输出作为参数传
递给 echo 命令,我们使⽤反引号将整个表达式括起来,这会告诉 shell 执⾏该命令并将其输出返回给 echo 命
令。
在这种情况下, index 函数将返回 3 ,因为 "ll" 第⼀次出现在 ${text} 中的第三个位置(从1开始计数)。
因此,命令的输出为 3 。
这个命令的作⽤是在给定的字符串 ${text} 中查找⼦串 "ll" 第⼀次出现的位置(从1开始)。
『示例源码』
#!/usr/bin/env bash
################### 使⽤单引号拼接字符串 ###################
name1='white'
str1='hello, '${name1}''
str2='hello, ${name1}'
echo ${str1}_${str2}
# Output:
# hello, white_hello, ${name1}
################### 使⽤双引号拼接字符串 ###################
name2="black"
str3="hello, "${name2}""
str4="hello, ${name2}"
echo ${str3}_${str4}
# Output:
# hello, black_hello, black
################### 获取字符串⻓度 ###################
text="12345"
echo "${text} length is: ${#text}"
# Output:
# 12345 length is: 5
# 获取⼦字符串
text="12345"
echo ${text:2:2}
# Output:
# 34
################### 查找⼦字符串 ###################
text="hello"
echo `expr index "${text}" ll`
# Output:
# 3
################### 判断字符串中是否包含⼦字符串 ###################
result=$(echo "${str}" | grep "feature/")
if [[ "$result" != "" ]]; then
echo "feature/ 是 ${str} 的⼦字符串"
else
echo "feature/ 不是 ${str} 的⼦字符串"
fi
################### 截取关键字左边内容 ###################
full_branch="feature/1.0.0"
branch=`echo ${full_branch#feature/}`
echo "branch is ${branch}"
################### 截取关键字右边内容 ###################
full_version="0.0.1-SNAPSHOT"
version=`echo ${full_version%-SNAPSHOT}`
echo "version is ${version}"
################### 字符串分割成数组 ###################
str="0.0.0.1"
OLD_IFS="$IFS"
IFS="."
array=( ${str} )
IFS="$OLD_IFS"
size=${#array[*]}
lastIndex=`expr ${size} - 1`
echo "数组⻓度:${size}"
echo "最后⼀个数组元素:${array[${lastIndex}]}"
for item in ${array[@]}
do
echo "$item"
done
################### 判断字符串是否为空 ###################
#-n 判断⻓度是否⾮零
#-z 判断⻓度是否为零
str=testing
str2=''
if [[ -n "$str" ]]
then
echo "The string $str is not empty"
else
echo "The string $str is empty"
fi
if [[ -n "$str2" ]]
then
echo "The string $str2 is not empty"
else
echo "The string $str2 is empty"
fi
# Output:
# The string testing is not empty
# The string is empty
################### 字符串⽐较 ###################
str=hello
str2=world
if [[ $str = "hello" ]]; then
echo "str equals hello"
else
echo "str not equals hello"
fi
if [[ $str2 = "hello" ]]; then
echo "str2 equals hello"
else
echo "str2 not equals hello"
fi
数组
bash 只⽀持⼀维数组。
数组下标从 0 开始,下标可以是整数或算术表达式,其值应⼤于或等于 0。
1 创建数组
shell 语⾔中⽀持关联数组。关联数组是⼀种基于键值对(key-value pairs)的数据结构,它允许你使⽤字符串或
数字作为索引来查找和访问数组元素。在 shell 中,关联数组可以使⽤ declare -A 命令或者在数组赋值时使⽤
+= 符号来定义
下⾯是⼀个简单的例⼦,展示了如何定义和使⽤关联数组:
# 声明关联数组,并为其指定元素
declare -A fruits
fruits=([apple]="red" [banana]="yellow" [kiwi]="green")
# 访问关联数组元素
echo "Apple is ${fruits[apple]} in color"
echo "Banana is ${fruits[banana]} in color"
echo "Kiwi is ${fruits[kiwi]} in color"
echo
# 循环输出所有键值对
for key in "${!fruits[@]}"
do
echo "index: $key value: ${fruits[$key]}"
done
上⾯的代码创建了⼀个名为 fruits 的关联数组,并且通过指定元素的⽅式为其赋值。然后使⽤
${fruits[apple]} 等⽅式访问元素值,它们的输出结果即为对应的颜⾊。最后⼀个循环⽤于输出所有键值对,
使⽤ ${!fruits[@]} 来获得所有的键名,再使⽤ ${fruits[$key]} 来获得对应的值。
# 创建数组的不同⽅式
nums=([2]=2 [0]=0 [1]=1)
colors=(red yellow "dark blue")
2 访问数组元素
nums=([2]=2 [0]=0 [1]=1)
colors=(red yellow "dark blue")
访问数组的单个元素:
echo ${nums[1]}
# Output: 1
访问数组的所有元素:
echo ${colors[*]}
# Output: red yellow dark blue
echo ${colors[@]}
# Output: red yellow dark blue
上⾯两⾏有很重要(也很微妙)的区别:
为了将数组中每个元素单独⼀⾏输出,我们⽤ printf 命令:
printf "+ %s\n" ${colors[*]}
# Output:
# + red
# + yellow
# + dark
# + blue
为什么 dark 和 blue 各占了⼀⾏?尝试⽤引号包起来:
printf "+ %s\n" "${colors[*]}"
# Output:
# + red yellow dark blue
printf "+ %s\n" "${colors[@]}"
# Output:
# + red
# + yellow
# + dark blue
在引号内, ${colors[@]} 将数组中的每个元素扩展为⼀个单独的参数;数组元素中的空格得以保留。
访问数组的部分元素:
echo ${nums[@]:0:2}
# Output:
# 0 1
在上⾯的例⼦中, ${array[@]} 扩展为整个数组, :0:2 取出了数组中从 0 开始,⻓度为 2 的元素。
3 访问数组⻓度
echo ${#nums[*]}
# Output:
# 3
4 向数组中添加元素
colors=(white "${colors[@]}" green black)
echo ${colors[@]}
# Output:
# white red yellow dark blue green black
上⾯的例⼦中, ${colors[@]} 扩展为整个数组,并被置换到复合赋值语句中,接着,对数组 colors 的赋值覆盖
了它原来的值。
5 从数组中删除元素
unset nums[0]
echo ${nums[@]}
# Output:
# 1 2
『示例源码』
#!/usr/bin/env bash
################### 创建数组 ###################
nums=( [2]=2 [0]=0 [1]=1 )
colors=( red yellow "dark blue" )
################### 访问数组的单个元素 ###################
echo ${nums[1]}
# Output: 1
################### 访问数组的所有元素 ###################
echo ${colors[*]}
# Output: red yellow dark blue
echo ${colors[@]}
# Output: red yellow dark blue
printf "+ %s\n" ${colors[*]}
# Output:
# + red
# + yellow
# + dark
# + blue
printf "+ %s\n" "${colors[*]}"
# Output:
# + red yellow dark blue
printf "+ %s\n" "${colors[@]}"
# Output:
# + red
# + yellow
# + dark blue
################### 访问数组的部分元素 ###################
echo ${nums[@]:0:2}
# Output:
# 0 1
################### 获取数组⻓度 ###################
echo ${#nums[*]}
# Output:
# 3
################### 向数组中添加元素 ###################
colors=( white "${colors[@]}" green black )
echo ${colors[@]}
# Output:
# white red yellow dark blue green black
################### 从数组中删除元素 ###################
unset nums[ 0 ]
echo ${nums[@]}
# Output:
# 1 2
运算符
1 算术运算符
假定变量 x 为 10,变量 y 为 20:
+ 加法 expr $x + $y 结果为 30。
- 减法 expr $x - $y 结果为 -10。
* 乘法 expr $x * $y 结果为 200。
/ 除法 expr $y / $x 结果为 2。
% 取余 expr $y % $x 结果为 0。
= 赋值 x=$y 将把变量 y 的值赋给 x。
== 相等 ⽤于⽐较两个字符串,相同则返回 true。 [ $x == $y ] 返回 false。
!= 不相等 ⽤于⽐较两个数字,不相同则返回 true。 [ $x != $y ] 返回 true。
⚠️:条件表达式要放在⽅括号之间,并且要有空格,例如: [$x==$y] 是错误的,必须写成 [ $x == $y ] 。
2 关系运算符
关系运算符只⽀持数字 ,不⽀持字符串,除⾮字符串的值是数字。
下表列出了常⽤的关系运算符,假定变量 a 为 10,变量b 为 20:
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否⼤于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否⼩于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否⼤于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否⼩于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。
『示例源码』
x=10
y=20
echo "x=${x}, y=${y}"
if [[ ${x} -eq ${y} ]]; then
echo "${x} -eq ${y} : x 等于 y"
else
echo "${x} -eq ${y}: x 不等于 y"
fi
if [[ ${x} -ne ${y} ]]; then
echo "${x} -ne ${y}: x 不等于 y"
else
echo "${x} -ne ${y}: x 等于 y"
fi
if [[ ${x} -gt ${y} ]]; then
echo "${x} -gt ${y}: x ⼤于 y"
else
echo "${x} -gt ${y}: x 不⼤于 y"
fi
if [[ ${x} -lt ${y} ]]; then
echo "${x} -lt ${y}: x ⼩于 y"
else
echo "${x} -lt ${y}: x 不⼩于 y"
fi
if [[ ${x} -ge ${y} ]]; then
echo "${x} -ge ${y}: x ⼤于或等于 y"
else
echo "${x} -ge ${y}: x ⼩于 y"
fi
if [[ ${x} -le ${y} ]]; then
echo "${x} -le ${y}: x ⼩于或等于 y"
else
echo "${x} -le ${y}: x ⼤于 y"
fi
# Output:
# x=10, y=20
# 10 -eq 20: x 不等于 y
# 10 -ne 20: x 不等于 y
# 10 -gt 20: x 不⼤于 y
# 10 -lt 20: x ⼩于 y
# 10 -ge 20: x ⼩于 y
# 10 -le 20: x ⼩于或等于 y
3 布尔运算符
下表列出了常⽤的布尔运算符,假定变量 a为 10,变量 b 为 20:
! ⾮运算,表达式为 true 则返回 false,否则返回true。 [ ! false ] 返回 true。
-o 或运算,有⼀个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回true。
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回false。
『示例源码』
x=10
y=20
echo "x=${x}, y=${y}"
if [[ ${x} != ${y} ]]; then
echo "${x} != ${y} : x 不等于 y"
else
echo "${x} != ${y}: x 等于 y"
fi
if [[ ${x} -lt 100 && ${y} -gt 15 ]]; then
echo "${x} ⼩于 100 且 ${y} ⼤于 15 : 返回 true"
else
echo "${x} ⼩于 100 且 ${y} ⼤于 15 : 返回 false"
fi
if [[ ${x} -lt 100 || ${y} -gt 100 ]]; then
echo "${x} ⼩于 100 或 ${y} ⼤于 100 : 返回 true"
else
echo "${x} ⼩于 100 或 ${y} ⼤于 100 : 返回 false"
fi
if [[ ${x} -lt 5 || ${y} -gt 100 ]]; then
echo "${x} ⼩于 5 或 ${y} ⼤于 100 : 返回 true"
else
echo "${x} ⼩于 5 或 ${y} ⼤于 100 : 返回 false"
fi
# Output:
# x=10, y=20
# 10 != 20 : x 不等于 y
# 10 ⼩于 100 且 20 ⼤于 15 : 返回 true
# 10 ⼩于 100 或 20 ⼤于 100 : 返回 true
# 10 ⼩于 5 或 20 ⼤于 100 : 返回 false
4 逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 x 为 10,变量 y 为 20:
&& 逻辑的 AND [[ ${x} -lt 100 && ${y} -gt 100 ]] 返回 false
|| 逻辑的 OR [[ ${x} -lt 100 || ${y} -gt 100 ]] 返回 true
『示例源码』
x=10
y=20
echo "x=${x}, y=${y}"
if [[ ${x} -lt 100 && ${y} -gt 100 ]]
then
echo "${x} -lt 100 && ${y} -gt 100 返回 true"
else
echo "${x} -lt 100 && ${y} -gt 100 返回 false"
fi
if [[ ${x} -lt 100 || ${y} -gt 100 ]]
then
echo "${x} -lt 100 || ${y} -gt 100 返回 true"
else
echo "${x} -lt 100 || ${y} -gt 100 返回 false"
fi
# Output:
# x=10, y=20
# 10 -lt 100 && 20 -gt 100 返回 false
# 10 -lt 100 || 20 -gt 100 返回 true
5 字符串运算符
下表列出了常⽤的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:
== 检测两个字符串是否相等,相等返回 true。 [ $a == $b ] 返回 false。
!= 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串⻓度是否为 0,为 0 返回 true。 [ -z $a ] 返回 false。
-n 检测字符串⻓度是否为 0,不为 0 返回 true。 [ -n $a ] 返回 true。
str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。
『示例源码』
x="abc"
y="xyz"
echo "x=${x}, y=${y}"
if [[ ${x} == ${y} ]]; then
echo "${x} = ${y} : x 等于 y"
else
echo "${x} = ${y}: x 不等于 y"
fi
if [[ ${x} != ${y} ]]; then
echo "${x} != ${y} : x 不等于 y"
else
echo "${x} != ${y}: x 等于 y"
fi
if [[ -z ${x} ]]; then
echo "-z ${x} : 字符串⻓度为 0"
else
echo "-z ${x} : 字符串⻓度不为 0"
fi
if [[ -n "${x}" ]]; then
echo "-n ${x} : 字符串⻓度不为 0"
else
echo "-n ${x} : 字符串⻓度为 0"
fi
if [[ ${x} ]]; then
echo "${x} : 字符串不为空"
else
echo "${x} : 字符串为空"
fi
# Output:
# x=abc, y=xyz
# abc = xyz: x 不等于 y
# abc != xyz : x 不等于 y
# -z abc : 字符串⻓度不为 0
# -n abc : 字符串⻓度不为 0
# abc : 字符串不为空
6 ⽂件测试运算符
⽂件测试运算符⽤于检测 Unix ⽂件的各种属性。
属性检测描述如下:
-b file 检测⽂件是否是块设备⽂件,如果是,则返回 true。 [ -b $file ] 返回false。
-c file 检测⽂件是否是字符设备⽂件,如果是,则返回 true。 [ -c $file ] 返回false。
-d file 检测⽂件是否是⽬录,如果是,则返回 true。 [ -d $file ] 返回false。
-f file 检测⽂件是否是普通⽂件(既不是⽬录,也不是设备⽂件),如果是,则返回 true。 [ -f $file ] 返回true。
-g file 检测⽂件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回false。
-k file 检测⽂件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回false。
-p file 检测⽂件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回false。
-u file 检测⽂件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回false。
-r file 检测⽂件是否可读,如果是,则返回 true。 [ -r $file ] 返回true。
-w file 检测⽂件是否可写,如果是,则返回 true。 [ -w $file ] 返回true。
-x file 检测⽂件是否可执⾏,如果是,则返回 true。 [ -x $file ] 返回true。
-s file 检测⽂件是否为空(⽂件⼤⼩是否⼤于 0),不为空返回 true。 [ -s $file ] 返回true。
-e file 检测⽂件(包括⽬录)是否存在,如果是,则返回 true。 [ -e $file ] 返回true。
『示例源码』
file="/etc/hosts"
if [[ -r ${file} ]]; then
echo "${file} ⽂件可读"
else
echo "${file} ⽂件不可读"
fi
if [[ -w ${file} ]]; then
echo "${file} ⽂件可写"
else
echo "${file} ⽂件不可写"
fi
if [[ -x ${file} ]]; then
echo "${file} ⽂件可执⾏"
else
echo "${file} ⽂件不可执⾏"
fi
if [[ -f ${file} ]]; then
echo "${file} ⽂件为普通⽂件"
else
echo "${file} ⽂件为特殊⽂件"
fi
if [[ -d ${file} ]]; then
echo "${file} ⽂件是个⽬录"
else
echo "${file} ⽂件不是个⽬录"
fi
if [[ -s ${file} ]]; then
echo "${file} ⽂件不为空"
else
echo "${file} ⽂件为空"
fi
if [[ -e ${file} ]]; then
echo "${file} ⽂件存在"
else
echo "${file} ⽂件不存在"
fi
# Output:(根据⽂件的实际情况,输出结果可能不同)
# /etc/hosts ⽂件可读
# /etc/hosts ⽂件可写
# /etc/hosts ⽂件不可执⾏
# /etc/hosts ⽂件为普通⽂件
# /etc/hosts ⽂件不是个⽬录
# /etc/hosts ⽂件不为空
# /etc/hosts ⽂件存在

浙公网安备 33010602011771号