bash shell快速备忘单

发布时间 2023-09-25 09:07:45作者: 往事已成昨天

linux bash shell 脚本的快速参考备忘单(全)

入门

hello.sh

#!/bin/bashVAR="world"echo "Hello $VAR!" # => Hello world!
执行脚本$ bash hello.sh

图片

 

变量

NAME="John"
echo ${NAME} # => John (变量)
echo $NAME # => John (变量)
echo "$NAME" # => John (变量)
echo '$NAME' # => $NAME (字符串原样输出)
echo "${NAME}!" # => John! (变量)
NAME = "John" # => Error (注意不能有空格)

 

图片

注释

# 这是一个内联 Bash 注释。单行注释

: '
这是一个
非常整洁的
bash 注释
'

多行注释使用 : ' 打开和 ' 关闭,注意空格。

 

图片

 

参数

$1 … $9 参数 1 ... 9
$0 脚本本身的名称
$1 第一个参数
${10} 位置参数 10
$# 参数数量
$$ shell 的进程 id
$* 所有参数
$@ 所有参数,从第一个开始
$- 当前选项
$_ 上一个命令的最后一个参数

 

 

图片

 

函数

get_name() {    echo "John"}echo "You are $(get_name)"
 

图片

 

条件句

if [[ -z "$string" ]]; then    echo "String is empty"elif [[ -n "$string" ]]; then    echo "String is not empty"fi
[[ -z STR ]] 空字符串
[[ -n STR ]] 非空字符串

 

大括号扩展

echo {A,B}.js

{A,B} 与 A B 相同
{A,B}.js 与 A.js B.js 相同
{1..5} 与 1 2 3 4 5 相同

图片

 

Shell 执行

# => I'm in /当前/的/路径
echo "I'm in $(PWD)"
# Same as:
echo "I'm in `pwd`"

图片

 

Bash 参数扩展

语法

${FOO%suffix} 删除后缀
${FOO#prefix} 删除前缀
${FOO%%suffix} 去掉长后缀
${FOO##prefix} 删除长前缀
${FOO/from/to} 替换第一个匹配项
${FOO//from/to} 全部替换
${FOO/%from/to} 替换后缀
${FOO/#from/to} 替换前缀

 

子字符串

${FOO:0:3} 子串 (位置,长度)
${FOO:(-3):3} 从右边开始的子串

图片

Length

${#FOO} $FOO 的长度

图片

默认值

${FOO:-val} $FOO,如果未设置,则为 val
${FOO:=val} 如果未设置,则将 $FOO 设置为 val
${FOO:+val} val 如果设置了$FOO
${FOO:?message} 如果 $FOO 未设置,则显示消息并退出

图片

 

替代 Substitution

 

echo ${food:-Cake}  #=> $food or "Cake"
STR="/path/to/foo.cpp"echo ${STR%.cpp} # /path/to/fooecho ${STR%.cpp}.o # /path/to/foo.oecho ${STR%/*} # /path/toecho ${STR##*.} # cpp (extension)echo ${STR##*/} # foo.cpp (basepath)echo ${STR#*/} # path/to/foo.cppecho ${STR##*/} # foo.cppecho ${STR/foo/bar} # /path/to/bar.cpp
 

 

切片 Slicing

name="John"echo ${name}           # => Johnecho ${name:0:2}       # => Joecho ${name::2}        # => Joecho ${name::-1}       # => Johecho ${name:(-1)}      # => necho ${name:(-2)}      # => hnecho ${name:(-2):2}    # => hn
length=2echo ${name:0:length} # => Jo
 

 

基本路径和目录路径

SRC="/path/to/foo.cpp"
BASEPATH=${SRC##*/} echo $BASEPATH # => "foo.cpp"
DIRPATH=${SRC%$BASEPATH}echo $DIRPATH # => "/path/to/"
 

 

Transform

STR="HELLO WORLD!"echo ${STR,}      # => hELLO WORLD!echo ${STR,,}     # => hello world!
STR="hello world!"echo ${STR^} # => Hello world!echo ${STR^^} # => HELLO WORLD!
ARR=(hello World)echo "${ARR[@],}" # => hello worldecho "${ARR[@]^}" # => Hello World

Bash 数组

定义数组

Fruits=('Apple' 'Banana' 'Orange')
Fruits[0]="Apple"Fruits[1]="Banana"Fruits[2]="Orange"
ARRAY1=(foo{1..2}) # => foo1 foo2ARRAY2=({A..D}) # => A B C D
# 合并 => foo1 foo2 A B C DARRAY3=(${ARRAY1[@]} ${ARRAY2[@]})
# 声明构造declare -a Numbers=(1 2 3)Numbers+=(4 5) # 附加 => 1 2 3 4 5

 

 

索引

${Fruits[0]} 第一个元素
${Fruits[-1]} 最后一个元素
${Fruits[*]} 所有元素
${Fruits[@]} 所有元素
${#Fruits[@]} 总数
${#Fruits} 第一节长度
${#Fruits[3]} 第n个长度
${Fruits[@]:3:2} 范围
${!Fruits[@]} 所有 Key

 

迭代 Iteration

Fruits=('Apple' 'Banana' 'Orange')for e in "${Fruits[@]}"; do    echo $edone
 

With index

for i in "${!Fruits[@]}"; do  printf "%s\t%s\n" "$i" "${Fruits[$i]}"done
 

 

操作

Fruits=("${Fruits[@]}" "Watermelon")         # 添加Fruits+=('Watermelon')                       # 也是添加Fruits=( ${Fruits[@]/Ap*/} )                 # 通过正则表达式匹配删除unset Fruits[2]                              # 删除一项Fruits=("${Fruits[@]}")                      # 复制Fruits=("${Fruits[@]}" "${Veggies[@]}")      # 连接lines=(`cat "logfile"`)                      # 从文件中读取
 

 

数组作为参数

function extract(){  local -n myarray=$1  local idx=$2  echo "${myarray[$idx]}"}Fruits=('Apple' 'Banana' 'Orange')extract Fruits 2     # => Orangle
 

 

Bash 字典

定义

declare -A sounds
sounds[dog]="bark"sounds[cow]="moo"sounds[bird]="tweet"sounds[wolf]="howl"
 

使用字典

echo ${sounds[dog]} # Dog's soundecho ${sounds[@]}   # All valuesecho ${!sounds[@]}  # All keysecho ${#sounds[@]}  # Number of elementsunset sounds[dog]   # Delete dog
 

 

迭代

for val in "${sounds[@]}"; do    echo $valdone

for key in "${!sounds[@]}"; do echo $keydone
 

Bash 条件句

整数条件

[[ NUM -eq NUM ]] 等于 Equal
[[ NUM -ne NUM ]] 不等于 Not equal
[[ NUM -lt NUM ]] 小于 Less than
[[ NUM -le NUM ]] 小于等于 Less than or equal
[[ NUM -gt NUM ]] 大于 Greater than
[[ NUM -ge NUM ]] 大于等于 Greater than or equal
(( NUM < NUM )) 小于
(( NUM <= NUM )) 小于或等于
(( NUM > NUM )) 比...更大
(( NUM >= NUM )) 大于等于

 

字符串条件

[[ -z STR ]] 空字符串
[[ -n STR ]] 非空字符串
[[ STR == STR ]] 相等
[[ STR = STR ]] 相等(同上)
[[ STR < STR ]] 小于 (ASCII)
[[ STR > STR ]] 大于 (ASCII)
[[ STR != STR ]] 不相等
[[ STR =~ STR ]] 正则表达式

 

例子

字符串

if [[ -z "$string" ]]; then    echo "String is empty"elif [[ -n "$string" ]]; then    echo "String is not empty"else    echo "This never happens"fi
 

组合

if [[ X && Y ]]; then    ...fi
 

相等

if [[ "$A" == "$B" ]]; then    ...fi
 

正则表达式

if [[ '1. abc' =~ ([a-z]+) ]]; then    echo ${BASH_REMATCH[1]}fi
 

小于

if (( $a < $b )); then   echo "$a is smaller than $b"fi
 

存在

if [[ -e "file.txt" ]]; then    echo "file exists"fi
 

文件条件

[[ -e FILE ]] 存在
[[ -d FILE ]] 目录
[[ -f FILE ]] 文件
[[ -h FILE ]] 符号链接
[[ -s FILE ]] 大小 > 0 字节
[[ -r FILE ]] 可读
[[ -w FILE ]] 可写
[[ -x FILE ]] 可执行文件
[[ f1 -nt f2 ]] f1 比 f2 新
[[ f1 -ot f2 ]] f2 比 f1 新
[[ f1 -ef f2 ]] 相同的文件

 

更多条件

[[ -o noclobber ]] 如果启用 OPTION
[[ ! EXPR ]] 不是 Not
[[ X && Y ]] 和 And
[[ X || Y ]] 或者 Or

 

逻辑和,或

if [ "$1" = 'y' -a $2 -gt 0 ]; then    echo "yes"fiif [ "$1" = 'n' -o $2 -lt 0 ]; then    echo "no"fi
 

 

Bash 循环

基本 for 循环

for i in /etc/rc.*; do    echo $idone
 

 

类似 C 的 for 循环

for ((i = 0 ; i < 100 ; i++)); do    echo $idone
 

 

范围

for i in {1..5}; do    echo "Welcome $i"done
 

步长

for i in {5..50..5}; do    echo "Welcome $i"done
 

 

自动递增

i=1while [[ $i -lt 4 ]]; do    echo "Number: $i"    ((i++))done
 

 

自动递减

i=3while [[ $i -gt 0 ]]; do    echo "Number: $i"    ((i--))done
 

 

Continue

for number in $(seq 1 3); do    if [[ $number == 2 ]]; then        continue;    fi    echo "$number"done

 

Break

for number in $(seq 1 3); do    if [[ $number == 2 ]]; then        # Skip entire rest of loop.        break;    fi    # This will only print 1    echo "$number"done
 

 

Until

count=0until [ $count -gt 10 ]; do    echo "$count"    ((count++))done
 

 

死循环

while true; do    # here is some code.done
 

 

死循环(简写)

while :; do    # here is some code.done
 

 

读取文件的每一行

cat file.txt | while read line; do    echo $linedone
 

 

Bash 函数

定义函数

myfunc() {  echo "hello $1"}
# 同上(替代语法)function myfunc() { echo "hello $1"}
myfunc "John"
 

返回值

myfunc() {    local myresult='some value'    echo $myresult}
result="$(myfunc)"
 

抛出错误

myfunc() {    return 1}
if myfunc; then echo "success"else echo "failure"fi
 

Bash 选项

选项

# 避免覆盖文件# (echo "hi" > foo)set -o noclobber
# 用于出错时退出# 避免级联错误set -o errexit
# 揭示隐藏的失败set -o pipefail
# 公开未设置的变量set -o nounset

 

全局选项

# 不匹配的 glob 被删除# ('*.foo' => '')shopt -s nullglob   
# 不匹配的 glob 抛出错误shopt -s failglob
# 不区分大小写的球体shopt -s nocaseglob
# 通配符匹配点文件# ("*.sh" => ".foo.sh")shopt -s dotglob
# 允许 ** 进行递归匹配
# ('lib/**/*.rb' => 'lib/a/b/c.rb')shopt -s globstar
 

 

Bash 历史

命令

history 显示历史
sudo !! 使用 sudo 运行上一个命令
shopt -s histverify 不要立即执行扩展结果

 

表达式

!$ 展开最新命令的最后一个参数
!* 展开最新命令的所有参数
!-n 展开第 n 个最近的命令
!n 展开历史中的第 n 个命令
!<command> 展开最近调用的命令 <command>

 

操作

!! 再次执行最后一条命令
!!:s/<FROM>/<TO>/ 在最近的命令中将第一次出现的 <FROM> 替换为 <TO>
!!:gs/<FROM>/<TO>/ 在最近的命令中将所有出现的 <FROM> 替换为 <TO>
!$:t 仅从最近命令的最后一个参数扩展基本名称
!$:h 仅从最近命令的最后一个参数展开目录

!! 和 !$ 可以替换为任何有效的扩展。

切片 Slices

!!:n 仅扩展最近命令中的第 n 个标记(命令为 0;第一个参数为 1)
!^ 从最近的命令展开第一个参数
!$ 从最近的命令中展开最后一个标记
!!:n-m 从最近的命令扩展令牌范围
!!:n-$ 从最近的命令中将第 n 个标记展开到最后

!! 可以替换为任何有效的扩展,即 !cat!-2!42 等。

杂项

数值计算

$((a + 200))      # Add 200 to $a
$(($RANDOM%200)) # Random number 0..199
 

 

子 shell

(cd somedir; echo "I'm now in $PWD")pwd # still in first directory
 

 

检查命令

command -V cd#=> "cd is a function/alias/whatever"
#=> "cd is a function/alias/whatever"
 
 

 

 

重定向

python hello.py > output.txt   # 标准输出到(文件)python hello.py >> output.txt  # 标准输出到(文件),追加python hello.py 2> error.log   # 标准错误到(文件)python hello.py 2>&1           # 标准错误到标准输出python hello.py 2>/dev/null    # 标准错误到(空null)python hello.py &>/dev/null    # 标准输出和标准错误到(空null)
python hello.py < foo.txt # 将 foo.txt 提供给 python 的标准输入
 

来源相对

source "${0%/*}/../share/foo.sh"

 

脚本目录

DIR="${0%/*}"

 

Case/switch

case "$1" in    start | up)    vagrant up    ;;    *)    echo "Usage: $0 {start|stop|ssh}"    ;;esac

 

陷阱错误

trap 'echo Error at about $LINENO' ERR
或者traperr() { echo "ERROR: ${BASH_SOURCE[1]} at about ${BASH_LINENO[0]}"}set -o errtracetrap traperr ERR
 

 

printf

printf "Hello %s, I'm %s" Sven Olga#=> "Hello Sven, I'm Olga
printf "1 + 1 = %d" 2#=> "1 + 1 = 2"
printf "Print a float: %f" 2#=> "Print a float: 2.000000"

 

获取选项

while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in    -V | --version )    echo $version    exit    ;;    -s | --string )    shift; string=$1    ;;    -f | --flag )    flag=1    ;;esac; shift; doneif [[ "$1" == '--' ]]; then shift; fi

 

检查命令的结果

if ping -c 1 google.com; then    echo "看来您的互联网连接正常"fi
 

 

grep 检查

if grep -q 'foo' ~/.bash_history; then    echo "您过去似乎输入过“foo”"fi

 

写入文件

cat 用于显示文本文件内容,全部输出
EOF end of file,表示文本结束符

cat > output.txt <<EOFthis is test eofthis is test eof2EOF
 

输出 cat output.txt

this is test eof
this is test eof2

追加内容

cat >>2.txt <<EOF456789EOF
 

$ 等特殊字符时,须利用转义字符 \

cat > file <<EOFexport ORACLE_SID=yqpt export PATH=\$PATH:\$ORACLE_HOME/bin  EOF
 

取消变量替换,EOF 被加上双引号或者单引号,即可取消变量的替换

cat << "EOF" > output.shecho "This is output"echo $1EOF
 

所有TAB键将全部忽略[不能是空格]

cat << -EOF        echo "This is output"EOF
 

特殊变量

$? 最后一个任务的退出状态
$! 最后一个后台任务的 PID
$$ shell PID
$0 shell 脚本的文件名

 

反斜杠转义

  •  

  • !

  • "

  • #

  • &

  • '

  • (

  • )

  • ,

  • ;

  • <

  • >

  • [

  • |

  • \

  • ]

  • ^

  • {

  • }

  • `

  • $

  • *

  • ?

使用 \ 转义这些特殊字符

Heredoc

cat <<ENDhello worldEND
 

 

转到上一个目录

pwd # /home/user/foocd bar/pwd # /home/user/foo/barcd -pwd # /home/user/foo
 

 

读取输入

echo -n "Proceed? [y/n]: "read ansecho $ans
read -n 1 ans # 只有一个字符
 

 

条件执行

git commit && git pushgit commit || echo "Commit failed"
 

 

严格模式

set -euo pipefailIFS=$'\n\t'
 

 

可选参数

args=("$@")args+=(foo)args+=(bar)echo "${args[@]}"
 

将参数放入数组中,然后追加

调试模式

启用调试模式,会把脚本中的每条命令的执行情况打印出来。它可以在整个会话或脚本上运行,也可以在脚本内以编程方式启用。

以调试模式运行脚本(整个脚本都会打印调试信息):

$ bash -x myscript.sh
 

在bash脚本中打开调试(针对部分内容打印调试信息)。

#!/bin/bashset -x   # Enable debugging# some code hereset +x   # Disable debugging output.
 

Bash 颜色

颜色着色语法示例

您可以通过为其输出着色来使您的 BASH 脚本更漂亮,使用以下模板编写彩色文本:

echo -e "\e[COLORm文字变色了\e[0m"
示例$ echo -e "\e[31m命令行中显示红色文字\e[0m"
命令行中显示红色文字$ echo -e "\e[42m绿色背景\e[0m"
 

绿色背景

-e 启用反斜杠转义的解释
\e[ 或 \x1b[ 或 \033[ 开始颜色修改
COLORm 颜色代码 + m 在末尾
\e[0m 或 \x1b[0m 或 \033[0m 结束颜色修改

0x1b 字面上称为 ESC

示例

$ echo -e "\e[3m下划线文本\e[0m"
下划线文本$ echo -e "\e[1;33;4;44m粗体下划线蓝色背景黄色文字的文本\e[0m"
 

粗体下划线蓝色背景黄色文字的文本

\e[         # 启用转义1;33;4;44   # 参数 (1;33;4;44)m           # 设置图形模式
 

样式

0 普通字符(复位或正常) 关闭所有属性
1 粗体  
2 弱化(降低强度) 未广泛支持
3 斜体 未广泛支持有时为反相显示
4 下划线  
5 缓慢闪烁  
6 快速闪烁  
7 反显  
8 隐藏 未广泛支持。
9 划除  

 

ANSI — 颜色转义码

颜色前景色背景色示例
Black 黑色 30 40 ``
Red 红色 31 41 ``
Green 绿色 32 42 ``
Yellow 黄色 33 43 ``
Blue 蓝色 34 44 ``
Purple 紫色 35 45 ``
Cyan 青色 36 46 ``
White 白色 37 47 ``

 

ANSI — 颜色转义码(亮色)

颜色前景色背景色示例
Bright Black(Gray) 灰色 90 100 ``
Bright Red 亮红色 91 101 ``
Bright Green 亮绿色 92 102 ``
Bright Yellow 亮黄色 93 103 ``
Bright Blue 亮蓝色 94 104 ``
Bright Magenta 亮紫色 95 105 ``
Bright Cyan 亮青色 96 106 ``
Bright White 浅灰 97 107 ``

 

可用功能

 

n A 光标上移 光标向指定的方向移动 n(默认1)格
n B 光标下移 光标向指定的方向移动 n(默认1)格
n C 光标前移 光标向指定的方向移动 n(默认1)格
n D 光标后移 光标向指定的方向移动 n(默认1)格
n E 光标移到下一行 光标移动到下面第 n(默认1)行的开头(非ANSI.SYS)
n F 光标移到上一行 光标移动到上面第 n(默认1)行的开头(非ANSI.SYS)
n G 光标水平绝对 光标移动到第 n(默认1)列(非ANSI.SYS)
n;m H 光标位置 光标移动到第 n行、第 m 列。值从1开始,且默认为1(左上角)
n J ED – 擦除显示 清除屏幕的部分区域
n K EL – 擦除行 清除行内的部分区域
n S SU – 向上滚动 整页向上滚动 n(默认1)行。新行添加到底部 (非ANSI.SYS)
n T SD – 向下滚动 整页向下滚动 n(默认1)行。新行添加到顶部 (非ANSI.SYS)
n;mf HVP – 水平垂直位置 同CUP
n m SGR – 选择图形再现 设置SGR参数,包括文字颜色
5i 打开辅助端口 启用辅助串行端口,通常用于本地串行打印机
4i 关闭辅助端口 禁用辅助串行端口,通常用于本地串行打印机
6n DSR – 设备状态报告 以 ESC[n;mR (就像在键盘上输入)向应用程序报告光标位置(CPR),其中 n是行, m 是列
s SCP – 保存光标位置 保存光标的当前位置
u RCP – 恢复光标位置 恢复保存的光标位置

参考网址:

  • Shell 教程 (jaywcjlove.github.io)

  • Devhints (devhints.io)

  • Bash-hackers wiki (bash-hackers.org)

  • Shell vars (bash-hackers.org)

  • Learn bash in y minutes (learnxinyminutes.com)

  • Bash Guide (mywiki.wooledge.org)

  • ShellCheck (shellcheck.net)

  • shell - Standard Shell (devmanual.gentoo.org)

  • ANSI 转义序列 (zh.wikipedia.org)

 

收录于合集 #linux
 10
上一篇Linux 教程下一篇Qt 音视频、V4L2摄像头编程、jpeg库
 
阅读 3150
Qt历险记
 
 
关注后可发消息