译者前言

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 位运算

操作符 说明
<< 按位左移
<< 按位左移
<< 按位左移
<< 按位左移
<< 按位左移
<< 按位左移
<< 按位左移
<< 按位左移
<< 按位左移
<< 按位左移
<< 按位左移

---The End ---