译者前言
pure bash bible 是Dylan Araps 在github 上发布的一本关于Linux bash 的电子书,实用性强。在此将其翻译为中文,既加深自己的理解,也为需要的朋友提供参考和帮助。翻译有错漏的地方,请各位予以指正,感谢!
前言
本书包含了一系列纯bash脚本实现的程序,用于替代相同功能的外部程序。bash 脚本语言功能强大,可以在不依赖外部程序的条件下,完成我们工作中的大部分的需求。
在bash 中调用外部程序是比较消耗资源的,会对脚本应用的执行效率带来明显的影响。使用纯bash脚本编写应用执行效率高,外部依赖少,还能帮助我们更好理解bash语言原生的功能。
本书的内容可以作为编写bash脚本应用中遇到问题提供参考。通过函数形式的样例代码演示了如何将这些解决方案应用到代码中。
1.字符串操作
1.1 移除字符串开头和结尾的空格
这是对sed, awk, perl及其它工具的一个替代。下面的函数找出字符串开头及结尾的空格,将它们从字符串中移除。bash内置的:用于代替临时变量。
函数示例
trim_string() {
# Usage: trim_string " example string "
: "${1#"${1%%[![:space:]]*}"}"
: "${_%"${_##*[![:space:]]}"}"
printf '%s\n' "$_"
}
使用示例
$ trim_string " Hello, World "
Hello, World
$ name=" John Black "
$ trim_string "$name"
John Black
1.2 移除字符串中的多余的空格
这是对sed, awk, perl及其它工具的一个替代。下面的函数移除字符串中多余的空格,保留单词之间的间隔。
函数示例
# shellcheck disable=SC2086,SC2048
trim_all() {
# Usage: trim_all " example string "
set -f
set -- $*
printf '%s\n' "$*"
set +f
}
使用示例
$ trim_all " Hello, World "
Hello, World
$ name=" John Black is my name. "
$ trim_all "$name"
John Black is my name.
1.3 对字符串进行匹配正则表达式匹配
bash 的正则表达式匹配功能可以在大部分的应用场景中替代sed工具。
注意:这是bash平台相关的功能之一。bash会使用系统中安装的正则表达式引擎来处理。如果需要保持兼容性,请指明使用POSIX POSIX regex 功能。
注意:该示例只返回首个matching group。当有多个matching group时,需要对示例进行修订。
函数示例
regex() {
# Usage: regex "string" "regex"
[[ $1 =~ $2 ]] && printf '%s\n' "${BASH_REMATCH[1]}"
}
使用示例
$ # Trim leading white-space.
$ regex ' hello' '^\s*(.*)'
hello
$ # Validate a hex color.
$ regex "#FFFFFF" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$'
#FFFFFF
$ # Validate a hex color (invalid).
$ regex "red" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$'
# no output (invalid)
在脚本中的使用示例
is_hex_color() {
if [[ $1 =~ ^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$ ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
else
printf '%s\n' "error: $1 is an invalid color."
return 1
fi
}
read -r color
is_hex_color "$color" || color="#FFFFFF"
# Do stuff.
1.4 根据指定的分隔符分割字符串
注意:需要bash 4及以上版本
可以作为 cut, awk 及其它根据的替代品。
函数示例
split() {
# Usage: split "string" "delimiter"
IFS=$'\n' read -d "" -ra arr <<< "${1//$2/$'\n'}"
printf '%s\n' "${arr[@]}"
}
使用示例
$ split "apples,oranges,pears,grapes" ","
apples
oranges
pears
grapes
$ split "1, 2, 3, 4, 5" ", "
1
2
3
4
5
# Multi char delimiters work too!
$ split "hello---world---my---name---is---john" "---"
hello
world
my
name
is
john
1.5 将字符串转换为小写
注意:需要bash 4及以上版本
函数示例
lower() {
# Usage: lower "string"
printf '%s\n' "${1,,}"
}
使用示例
$ lower "HELLO"
hello
$ lower "HeLlO"
hello
$ lower "hello"
hello
1.6 将字符串转换为大写
注意:需要bash 4及以上版本
函数示例
upper() {
# Usage: upper "string"
printf '%s\n' "${1^^}"
}
使用示例
$ upper "hello"
HELLO
$ upper "HeLlO"
HELLO
$ upper "HELLO"
HELLO
1.7 反转字符串的大小写
注意:需要bash 4及以上版本
函数示例
reverse_case() {
# Usage: reverse_case "string"
printf '%s\n' "${1~~}"
}
使用示例
$ reverse_case "hello"
HELLO
$ reverse_case "HeLlO"
hElLo
$ reverse_case "HELLO"
hello
1.8 删除字符串中的引号
函数示例
trim_quotes() {
# Usage: trim_quotes "string"
: "${1//\'}"
printf '%s\n' "${_//\"}"
}
使用示例
$ var="'Hello', \"World\""
$ trim_quotes "$var"
Hello, World
1.9 在字符串中移除所有满足匹配模式的实例
函数示例
strip_all() {
# Usage: strip_all "string" "pattern"
printf '%s\n' "${1//$2}"
}
使用示例
$ strip_all "The Quick Brown Fox" "[aeiou]"
Th Qck Brwn Fx
$ strip_all "The Quick Brown Fox" "[[:space:]]"
TheQuickBrownFox
$ strip_all "The Quick Brown Fox" "Quick "
The Brown Fox
1.10 在字符串中移除首项满足匹配模式的实例
函数示例
strip() {
# Usage: strip "string" "pattern"
printf '%s\n' "${1/$2}"
}
使用示例
$ strip "The Quick Brown Fox" "[aeiou]"
Th Quick Brown Fox
$ strip "The Quick Brown Fox" "[[:space:]]"
TheQuick Brown Fox
1.11 在字符串开头删除满足匹配模式的实例
函数示例
lstrip() {
# Usage: lstrip "string" "pattern"
printf '%s\n' "${1##$2}"
}
使用示例
$ lstrip "The Quick Brown Fox" "The "
Quick Brown Fox
1.12 在字符串结尾删除满足匹配模式的实例
函数示例
rstrip() {
# Usage: rstrip "string" "pattern"
printf '%s\n' "${1%%$2}"
}
使用示例
$ rstrip "The Quick Brown Fox" " Fox"
The Quick Brown
1.13 对字符串进行URL 编码
函数示例
urlencode() {
# Usage: urlencode "string"
local LC_ALL=C
for (( i = 0; i < ${#1}; i++ )); do
: "${1:i:1}"
case "$_" in
[a-zA-Z0-9.~_-])
printf '%s' "$_"
;;
*)
printf '%%%02X' "'$_"
;;
esac
done
printf '\n'
}
使用示例
$ urlencode "https://github.com/dylanaraps/pure-bash-bible"
https%3A%2F%2Fgithub.com%2Fdylanaraps%2Fpure-bash-bible
1.14 对字符串进行URL 解码
函数示例
urldecode() {
# Usage: urldecode "string"
: "${1//+/ }"
printf '%b\n' "${_//%/\\x}"
}
使用示例
$ urldecode "https%3A%2F%2Fgithub.com%2Fdylanaraps%2Fpure-bash-bible"
https://github.com/dylanaraps/pure-bash-bible
1.15 检查字符串中是否包含另一个字符串
使用条件测试方式
if [[ $var == *sub_string* ]]; then
printf '%s\n' "sub_string is in var."
fi
# Inverse (substring not in string).
if [[ $var != *sub_string* ]]; then
printf '%s\n' "sub_string is not in var."
fi
# This works for arrays too!
if [[ ${arr[*]} == *sub_string* ]]; then
printf '%s\n' "sub_string is in array."
fi
case 方式
case "$var" in
*sub_string*)
# Do stuff
;;
*sub_string2*)
# Do more stuff
;;
*)
# Else
;;
esac
1.16 检查字符串中是否以另一个字符串开头
if [[ $var == sub_string* ]]; then
printf '%s\n' "var starts with sub_string."
fi
# Inverse (var does not start with sub_string).
if [[ $var != sub_string* ]]; then
printf '%s\n' "var does not start with sub_string."
fi
1.17 检查字符串中是否以另一个字符串结尾
if [[ $var == *sub_string ]]; then
printf '%s\n' "var ends with sub_string."
fi
# Inverse (var does not end with sub_string).
if [[ $var != *sub_string ]]; then
printf '%s\n' "var does not end with sub_string."
fii
2. 数组
2.1 反转数组的顺序
启用extdebug 允许脚本访问BASH_ARGV数组,该数组以逆序方式存储当前函数的参数。
注:需要bash 5.0 以上的shopt -s compat44 in +.
函数示例
reverse_array() {
# Usage: reverse_array "array"
shopt -s extdebug
f()(printf '%s\n' "${BASH_ARGV[@]}"); f "$@"
shopt -u extdebug
}
使用示例
$ reverse_array 1 2 3 4 5
5
4
3
2
1
$ arr=(red blue green)
$ reverse_array "${arr[@]}"
green
blue
red
2.2 移除数组中重复的元素
注:需要bash 4.0 以上版本
注:List order may not stay the same.
函数示例
remove_array_dups() {
# Usage: remove_array_dups "array"
declare -A tmp_array
for i in "$@"; do
[[ $i ]] && IFS=" " tmp_array["${i:- }"]=1
done
printf '%s\n' "${!tmp_array[@]}"
}
使用示例
$ remove_array_dups 1 1 2 2 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5 5
1
2
3
4
5
$ arr=(red red green blue blue)
$ remove_array_dups "${arr[@]}"
red
green
blue
2.3 随机返回数组中的元素
函数示例
random_array_element() {
# Usage: random_array_element "array"
local arr=("$@")
printf '%s\n' "${arr[RANDOM % $#]}"
}
使用示例
$ array=(red green blue yellow brown)
$ random_array_element "${array[@]}"
yellow
# Multiple arguments can also be passed.
$ random_array_element 1 2 3 4 5 6 7
3
2.4 循环遍历一个数组
下面的样例代码中,每执行cycle一次将会顺序从数组arr中取出一个元素,并通过printf 输出到界面上。当到达arr的最后一个元素后,会重新跳回到第一个元素。
arr=(a b c d)
cycle() {
printf '%s ' "${arr[${i:=0}]}"
((i=i>=${#arr[@]}-1?0:++i))
}
2.5 在两个值间来回切换
下面的用法与2.4的一致,只是一个不同的使用例子。
arr=(true false)
cycle() {
printf '%s ' "${arr[${i:=0}]}"
((i=i>=${#arr[@]}-1?0:++i))
}
3. 循环
3.1 在指定的数字范围内循环
可以替代seq
# Loop from 0-100 (no variable support).
for i in {0..100}; do
printf '%s\n' "$i"
done
3.2 在变量指定的范围内循环
可以替代seq
# Loop from 0-VAR.
VAR=50
for ((i=0;i<=VAR;i++)); do
printf '%s\n' "$i"
done
3.3 循环遍历一个数组
arr=(apples oranges tomatoes)
# Just elements.
for element in "${arr[@]}"; do
printf '%s\n' "$element"
done
3.4 通过索引循环遍历一个数组
arr=(apples oranges tomatoes)
# Elements and index.
for i in "${!arr[@]}"; do
printf '%s\n' "${arr[i]}"
done
# Alternative method.
for ((i=0;i<${#arr[@]};i++)); do
printf '%s\n' "${arr[i]}"
done
3.5 循环遍历文件的内容
while read -r line; do
printf '%s\n' "$line"
done < "file"
3.6 循环遍历文件及目录
# Greedy example.
for file in *; do
printf '%s\n' "$file"
done
# PNG files in dir.
for file in ~/Pictures/*.png; do
printf '%s\n' "$file"
done
# Iterate over directories.
for dir in ~/Downloads/*/; do
printf '%s\n' "$dir"
done
# Brace Expansion.
for file in /path/to/parentdir/{file1,file2,subdir/file3}; do
printf '%s\n' "$file"
done
# Iterate recursively.
shopt -s globstar
for file in ~/Pictures/**/*; do
printf '%s\n' "$file"
done
shopt -u globstar
4. 文件处理
注:bash低于4.4版本 不能正确处理二进制数据。
4.1 将文件内容读入到一个字符串
可以作为cat 命令的替代
file_data="$(<"file")"
4.2 按行将文件内容读入到一个数组
可以作为cat 命令的替代
# Bash <4 (discarding empty lines).
IFS=$'\n' read -d "" -ra file_data < "file"
# Bash <4 (preserving empty lines).
while read -r line; do
file_data+=("$line")
done < "file"
# Bash 4+
mapfile -t file_data < "file"
4.3 获取文件的前N行
可以作为head 命令的替代
注:需要4.0以上版本的bash
函数示例
head() {
# Usage: head "n" "file"
mapfile -tn "$1" line < "$2"
printf '%s\n' "${line[@]}"
}
使用示例
$ head 2 ~/.bashrc
# Prompt
PS1='➜ '
$ head 1 ~/.bashrc
# Prompt
4.4 获取文件的后N行
可以作为tail 命令的替代
注:需要4.0以上版本的bash
函数示例
tail() {
# Usage: tail "n" "file"
mapfile -tn 0 line < "$2"
printf '%s\n' "${line[@]: -$1}"
}
使用示例
$ tail 2 ~/.bashrc
# Enable tmux.
# [[ -z "$TMUX" ]] && exec tmux
$ tail 1 ~/.bashrc
# [[ -z "$TMUX" ]] && exec tmux
4.5 获取文件的行数
可以作为 wc -l 命令的替代
函数示例(bash 4)
lines() {
# Usage: lines "file"
mapfile -tn 0 lines < "$1"
printf '%s\n' "${#lines[@]}"
}
函数示例(bash 3)
这个方法比mapfile方法使用更少的内存,并且可以在bash 3 执行。但这个方法在处理大文件时比较慢。
lines_loop() {
# Usage: lines_loop "file"
count=0
while IFS= read -r _; do
((count++))
done < "$1"
printf '%s\n' "$count"
}
使用示例
$ lines ~/.bashrc
48
$ lines_loop ~/.bashrc
48
4.6 获取目录中包含的文件或目录的数量
这是通过将glob的输出传递给函数然后计算参数的数量来实现的。
函数示例
count() {
# Usage: count /path/to/dir/*
# count /path/to/dir/*/
printf '%s\n' "$#"
}
使用示例
# Count all files in dir.
$ count ~/Downloads/*
232
# Count all dirs in dir.
$ count ~/Downloads/*/
45
# Count all jpg files in dir.
$ count ~/Pictures/*.jpg
64
4.7 创建一个空文件
可以作为touch 命令的替代
# Shortest.
>file
# Longer alternatives:
:>file
echo -n >file
printf '' >file
4.8 提取两个标记间的行
函数示例
extract() {
# Usage: extract file "opening marker" "closing marker"
while IFS=$'\n' read -r line; do
[[ $extract && $line != "$3" ]] &&
printf '%s\n' "$line"
[[ $line == "$2" ]] && extract=1
[[ $line == "$3" ]] && extract=
done < "$1"
}
使用示例
# Extract code blocks from MarkDown file.
$ extract ~/projects/pure-bash/README.md '```sh' '```'
# Output here...
5. 文件路径
5.1 获取文件路径中的目录
可以替代dirname 命令
函数示例
dirname() {
# Usage: dirname "path"
local tmp=${1:-.}
[[ $tmp != *[!/]* ]] && {
printf '/\n'
return
}
tmp=${tmp%%"${tmp##*[!/]}"}
[[ $tmp != */* ]] && {
printf '.\n'
return
}
tmp=${tmp%/*}
tmp=${tmp%%"${tmp##*[!/]}"}
printf '%s\n' "${tmp:-/}"
}
使用示例
$ dirname ~/Pictures/Wallpapers/1.jpg
/home/black/Pictures/Wallpapers
$ dirname ~/Pictures/Downloads/
/home/black/Pictures
5.2 获取文件路径中的basename
可以替代basename 命令
函数示例
basename() {
# Usage: basename "path" ["suffix"]
local tmp
tmp=${1%"${1##*[!/]}"}
tmp=${tmp##*/}
tmp=${tmp%"${2/"$tmp"}"}
printf '%s\n' "${tmp:-/}"
}
使用示例
$ basename ~/Pictures/Wallpapers/1.jpg
1.jpg
$ basename ~/Pictures/Wallpapers/1.jpg .jpg
1
$ basename ~/Pictures/Downloads/
Downloads
6. 变量
6.1 分配并使用一个变量
$ hello_world="value"
# Create the variable name.
$ var="world"
$ ref="hello_$var"
# Print the value of the variable name stored in 'hello_$var'.
$ printf '%s\n' "${!ref}"
value
在 bash 4.3+以上版本:
$ hello_world="value"
$ var="world"
# Declare a nameref.
$ declare -n ref=hello_$var
$ printf '%s\n' "$ref"
value
6.2 基于另一个变量的值命名新的变量
$ var="world"
$ declare "hello_$var=value"
$ printf '%s\n' "$hello_world"
value
7. 转义序列
与我们一般的想法相反,使用原始的转义序列并不会带来问题。使用 tput 抽象系统的ANSI序列就像手工打印一样麻烦。更糟糕的是,tput 实际上在不同的系统中并不是兼容的. 有许多tput变体,每个变体都有不同的命令和语法 (例如在FreeBSD 系统上使用tput setaf 3)。 原始的转义序列会更好用。
7.1 文本颜色
注:序列中的RGB值仅在真彩色的终端上才有效
序列 | 说明 | 参数值 |
---|---|---|
\e[38;5;<NUM>m |
设置文本前景色. | 0-255 |
\e[48;5;<NUM>m |
设置文本背景色. | 0-255 |
\e[38;2;<R>;<G>;<B>m |
设置文本前景色为RGB颜色. | R ,G ,B |
\e[48;2;<R>;<G>;<B>m |
设置文本背景色为RGB颜色. | R ,G ,B |
7.2 文本属性
序列 | 说明 |
---|---|
```\e[m | ``` |
```\e[1m | ``` |
```\e[2m | ``` |
```\e[3m | ``` |
```\e[4m | ``` |
```\e[5m | ``` |
```\e[7m | ``` |
```\e[8m | ``` |
```\e[9m | ``` |
7.3 光标移动
序列 | 说明 | 参数值 |
---|---|---|
\e[<LINE>;<COLUMN>H |
光标移动到绝对位置. | line ,column |
\e[H |
光标移动到原点(0,0). | |
\e[<NUM>A |
光标向上移动N行. | num |
\e[<NUM>B |
光标向下移动N行. | num |
\e[<NUM>C |
光标向右移动N行. | num |
\e[<NUM>D |
光标向左移动N行. | num |
\e[s |
保存光标位置. | |
\e[u |
恢复光标位置. |
7.4 删除文本
序列 | 说明 |
---|---|
\e[K |
删除当前光标位置到行末的所有文本. |
\e[1K |
删除当前光标位置到行首的所有文本. |
\e[2K |
删除当前行. |
\e[J |
删除当前行到屏幕底部的所有行. |
\e[1J |
删除当前行到屏幕顶部的所有行. |
\e[2J |
清除屏幕. |
\e[2J\e[H |
清除屏幕,光标回到原点(0,0). |
8. 参数扩展
8.1 变量的间接访问
参数 | 说明 |
---|---|
${!VAR} |
访问名字为VAR的值的变量. |
${!VAR*} |
将名字以VAR的值开头的变量值扩展为列表,并以 ITS 分割 |
${!VAR@} |
将名字以VAR的值开头的变量值扩展为列表,并以 ITS 分割,如果是双引号,则每个变量名称都会扩展为单独的单词. |
8.2 替换
参数 | 说明 |
---|---|
${VAR#PATTERN} |
移除VAR中从开始到第一次与模式匹配的左边的字符. |
${VAR##PATTERN} |
移除VAR中从开始到最后一次与模式匹配的左边的字符. |
${VAR%PATTERN} |
移除VAR中从结尾开始到第一次与模式匹配的右边的字符. |
${VAR%%PATTERN} |
移除VAR中从结尾开始到最后一次与模式匹配的右边的字符. |
${VAR/PATTERN/REPLACE} |
替换第一次匹配的字符. |
${VAR//PATTERN/REPLACE} |
替换所有匹配的字符. |
${VAR/PATTERN} |
删除第一次匹配的字符. |
${VAR//PATTERN} |
删除所有匹配的字符. |
8.3 长度
参数 | 说明 |
---|---|
${#VAR} |
变量中包含的字符长度. |
${#ARR[@]} |
数组中包含的元素的个数 |
8.4 扩展
参数 | 说明 |
---|---|
${VAR:OFFSET} |
从变量中移除开头的OFFSET个字符. |
${VAR:OFFSET:LENGTH} |
获得从OFFSET字符之后LENGTH个字符的字符串. |
${VAR:: OFFSET} |
获取变量的开头的OFFSET个字符. |
${VAR:: -OFFSET} |
从变量中删除结尾的OFFSET个字符. |
${VAR: -OFFSET} |
从变量中获取结尾的OFFSET个字符. |
${VAR:OFFSET:-OFFSET} |
从变量中删除从OFFSET字符之后LENGTH个字符. |
8.5 调整大小写
参数 | 说明 | 版本要求 |
---|---|---|
${VAR^} | 首字符大写 | bash 4+ |
${VAR^^} | 所有字符大写 | bash 4+ |
${VAR,} | 首字符小写 | bash 4+ |
${VAR,,} | 所有字符小写 | bash 4+ |
${VAR~} | 首字符大小写反转 | bash 4+ |
${VAR~~} | 所有字符大小写反转 | bash 4+ |
8.6 缺省值
参数 | 说明 |
---|---|
${VAR:-STRING} |
如果VAR为空 或者没有设置,则使用STRING作为它的值. |
${VAR-STRING} |
如果VAR为空,则使用STRING作为它的值. |
${VAR:=STRING} |
如果VAR为空 或者没有设置,则将变量VAR设置为STRING. |
${VAR=STRING} |
如果VAR没有设置,则将变量VAR设置为STRING. |
${VAR:+STRING} |
如果VAR不为空,则使用STRING作为它的值. |
${VAR+STRING} |
如果VAR已经设置,则使用STRING作为它的值. |
${VAR:?STRING} |
如果VAR为空,则显示一个错误. |
${VAR?STRING} |
如果VAR没有设置,则显示一个错误. |
9. 花括号扩展
9.1 范围
# 用法: {<START>..<END>}
# 打印数字 1-100.
echo {1..100}
# 打印浮点数范围.
echo 1.{1..9}
# 打印字符 a-z.
echo {a..z}
echo {A..Z}
# 嵌套.
echo {A..Z}{0..9}
# 打印用零填充的数字..
# 版本要求: bash 4+
echo {01..100}
# 更改增量
# 用法: {<START>..<END>..<INCREMENT>}
# 版本要求: bash 4+
echo {1..10..2} # 以2为增量.
9.2 字符串列表
echo {apples,oranges,pears,grapes}
# 使用示例:
# 删除~/Downloads/ 目录下的 Movies, Music 和 ISOS文件夹 .
rm -rf ~/Downloads/{Movies,Music,ISOS}
10. 条件表达式
10.1 文件条件判断
表达式 | 值 | 说明 |
---|---|---|
-a | file | 文件存在 |
-b | file | 文件存在且是块设备文件(block special file) |
-c | file | 文件存在且是字符设备文件(character special file) |
-d | file | 文件存在且是一个目录 |
-e | file | 文件存在 |
-f | file | 文件存在且是一个普通文件 |
-g | file | 文件存在且已经设置set-group-id位 |
-h | file | 文件存在并且是符号链接. |
-k | file | 文件存在且已经设置sticky-bita位 |
-p | file | 文件存在并且是命名管道 (FIFO). |
-r | file | 文件存在且可读 |
-s | file | 文件存在且其大小大于零. |
-t | file | 文件描述符是打开的并且引用到一个终端. |
-u | file | 文件存在且其set-user-id位已设置. |
-w | file | 文件存在且可写. |
-x | file | 文件存在且可执行. |
-G | file | 文件存在且拥有者是一个有效组ID. |
-L | file | 文件存在并且是符号链接. |
-N | file | 文件存在且自上次读取后已被修改. |
-O | file | 文件存在并且拥有者是一个有效用户ID. |
-S | file | 文件存在且是套接字. |
10.2 文件比较
表达式 | 说明 |
---|---|
file -ef file2 | 两个文件都引用相同的inode和设备编号. |
file -nt file2 | 是否 file 比 file2更新 (使用修改时间) 或者 file 存在而 file2 不存在. |
file -ef file2 | 是否 file 比 file2更旧 (使用修改时间) 或者 file2 存在而 file 不存在. |
10.3 变量条件
表达式 | 值 | 说明 |
---|---|---|
-o | opt | 是否启用了shell选项. |
-v | var | 是否变量具有指定的值. |
-R | opt | 是否变量是一个名称引用. |
-z | opt | 是否字符串的长度为零. |
-n | opt | 是否字符串的长度不为0 |
10.3 变量比较
表达式 | 说明 |
---|---|
var = var2 | 等于 |
var == var2 | 等于 (同义词 =). |
var != var2 | 不等于 |
var < var2 | 小于 (以ASCII字母顺序排列.) |
var > var2 | 大于 (以ASCII字母顺序排列.) |
11. 算术运算符
11.1 赋值
操作符 | 说明 |
---|---|
= | 对变量的值进行初始化或者修改 |
11.2 算术运算符
操作符 | 说明 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
** | 幂运算 |
% | 模 |
+= | 加等于(增加一个变量) |
-= | 减等于(减少一个变量) |
*= |
乘等于(乘一个变量) |
/= |
除等于(除一个变量) |
= | 模等于(先取模后赋值) |
11.2 位运算
操作符 | 说明 |
---|---|
<< | 按位左移 |
<< | 按位左移 |
<< | 按位左移 |
<< | 按位左移 |
<< | 按位左移 |
<< | 按位左移 |
<< | 按位左移 |
<< | 按位左移 |
<< | 按位左移 |
<< | 按位左移 |
<< | 按位左移 |