doc: docs/bash.md

This commit is contained in:
jaywcjlove 2024-04-09 17:57:37 +08:00
parent 104f34dff9
commit 0bced7ac0f

View File

@ -61,6 +61,7 @@ bash 注释
`$@` | 所有参数,从第一个开始 `$@` | 所有参数,从第一个开始
`$-` | 当前选项 `$-` | 当前选项
`$_` | 上一个命令的最后一个参数 `$_` | 上一个命令的最后一个参数
<!--rehype:className=left-align-->
见:[特殊参数](http://wiki.bash-hackers.org/syntax/shellvars#special_parameters_and_shell_variables) 见:[特殊参数](http://wiki.bash-hackers.org/syntax/shellvars#special_parameters_and_shell_variables)
@ -152,6 +153,7 @@ Bash 参数扩展
`${FOO:=val}` | 如果未设置,则将 `$FOO` 设置为 `val` `${FOO:=val}` | 如果未设置,则将 `$FOO` 设置为 `val`
`${FOO:+val}` | `val` 如果设置了`$FOO` `${FOO:+val}` | `val` 如果设置了`$FOO`
`${FOO:?message}` | 如果 `$FOO` 未设置,则显示消息并退出 `${FOO:?message}` | 如果 `$FOO` 未设置,则显示消息并退出
<!--rehype:className=code-nowrap left-align-->
### 替代 Substitution ### 替代 Substitution
@ -195,15 +197,21 @@ echo ${name:0:length} # => Jo
SRC="/path/to/foo.cpp" SRC="/path/to/foo.cpp"
``` ```
---
```bash ```bash
BASEPATH=${SRC##*/} BASEPATH=${SRC##*/}
echo $BASEPATH # => "foo.cpp" echo $BASEPATH # => "foo.cpp"
```
---
```bash
DIRPATH=${SRC%$BASEPATH} DIRPATH=${SRC%$BASEPATH}
echo $DIRPATH # => "/path/to/" echo $DIRPATH # => "/path/to/"
``` ```
### Transform ### 转换
```bash ```bash
STR="HELLO WORLD!" STR="HELLO WORLD!"
@ -265,7 +273,7 @@ for e in "${Fruits[@]}"; do
done done
``` ```
#### With index #### 有索引
```bash ```bash
for i in "${!Fruits[@]}"; do for i in "${!Fruits[@]}"; do
@ -348,12 +356,12 @@ Bash 条件句
条件 | 描述 条件 | 描述
:- | - :- | -
`[[ NUM -eq NUM ]]` | 等于 <yel>Eq</yel>ual | `[[ NUM -eq NUM ]]` | 等于 <yel>Eq</yel>ual
`[[ NUM -ne NUM ]]` | 不等于 <yel>N</yel>ot <yel>e</yel>qual | `[[ NUM -ne NUM ]]` | 不等于 <yel>N</yel>ot <yel>e</yel>qual
`[[ NUM -lt NUM ]]` | 小于 <yel>L</yel>ess <yel>t</yel>han | `[[ NUM -lt NUM ]]` | 小于 <yel>L</yel>ess <yel>t</yel>han
`[[ NUM -le NUM ]]` | 小于等于 <yel>L</yel>ess than or <yel>e</yel>qual | `[[ NUM -le NUM ]]` | 小于等于 <yel>L</yel>ess than or <yel>e</yel>qual
`[[ NUM -gt NUM ]]` | 大于 <yel>G</yel>reater <yel>t</yel>han | `[[ NUM -gt NUM ]]` | 大于 <yel>G</yel>reater <yel>t</yel>han
`[[ NUM -ge NUM ]]` | 大于等于 <yel>G</yel>reater than or <yel>e</yel>qual | `[[ NUM -ge NUM ]]` | 大于等于 <yel>G</yel>reater than or <yel>e</yel>qual
`(( NUM < NUM ))` | 小于 `(( NUM < NUM ))` | 小于
`(( NUM <= NUM ))` | 小于或等于 `(( NUM <= NUM ))` | 小于或等于
`(( NUM > NUM ))` | 比...更大 `(( NUM > NUM ))` | 比...更大
@ -448,10 +456,10 @@ fi
条件 | 描述 条件 | 描述
:- | - :- | -
`[[ -o noclobber ]]` | 如果启用 OPTION `[[ -o noclobber ]]` | 如果启用 <pur>OPTION</pur>
`[[ ! EXPR ]]` | 不是 Not `[[ ! EXPR ]]` | 不是 <pur>Not</pur>
`[[ X && Y ]]` | 和 And `[[ X && Y ]]` | 和 <pur>And</pur>
`[[ X \|\| Y ]]` | 或者 Or `[[ X \|\| Y ]]` | 或者 <pur>Or</pur>
### 逻辑和,或 ### 逻辑和,或
@ -536,10 +544,10 @@ done
```bash ```bash
for number in $(seq 1 3); do for number in $(seq 1 3); do
if [[ $number == 2 ]]; then if [[ $number == 2 ]]; then
# Skip entire rest of loop. # 跳过整个循环的其余部分。
break; break;
fi fi
# This will only print 1 # 这只会打印 1
echo "$number" echo "$number"
done done
``` ```
@ -558,7 +566,7 @@ done
```bash ```bash
while true; do while true; do
# here is some code. # 下面是一些代码
done done
``` ```
@ -566,7 +574,7 @@ done
```bash ```bash
while :; do while :; do
# here is some code. # 下面是一些代码
done done
``` ```
@ -589,8 +597,9 @@ myfunc() {
} }
``` ```
同上(替代语法)
```bash ```bash
# 同上(替代语法)
function myfunc() { function myfunc() {
echo "hello $1" echo "hello $1"
} }
@ -635,42 +644,61 @@ Bash 选项
### 选项 ### 选项
避免覆盖文件
```bash ```bash
# 避免覆盖文件
# (echo "hi" > foo) # (echo "hi" > foo)
set -o noclobber set -o noclobber
```
# 用于出错时退出 用于出错时退出,避免级联错误
# 避免级联错误
```bash
set -o errexit set -o errexit
```
# 揭示隐藏的失败 揭示隐藏的失败
```bash
set -o pipefail set -o pipefail
```
# 公开未设置的变量 公开未设置的变量
```bash
set -o nounset set -o nounset
``` ```
### 全局选项 ### 全局选项
不匹配的 glob 被删除
```bash ```bash
# 不匹配的 glob 被删除 shopt -s nullglob # ('*.foo' => '')
# ('*.foo' => '') ```
shopt -s nullglob
# 不匹配的 glob 抛出错误 不匹配的 glob 抛出错误
```bash
shopt -s failglob shopt -s failglob
```
# 不区分大小写的球体 不区分大小写的球体
```bash
shopt -s nocaseglob shopt -s nocaseglob
```
# 通配符匹配点文件 通配符匹配点文件
# ("*.sh" => ".foo.sh")
shopt -s dotglob
# 允许 ** 进行递归匹配 ```bash
# ('lib/**/*.rb' => 'lib/a/b/c.rb') shopt -s dotglob # ("*.sh" => ".foo.sh")
shopt -s globstar ```
允许 ** 进行递归匹配
```bash
shopt -s globstar # ('lib/**/*.rb' => 'lib/a/b/c.rb')
``` ```
Bash 历史 Bash 历史
@ -682,8 +710,9 @@ Bash 历史
命令 | 描述 命令 | 描述
:- | - :- | -
`history` | 显示历史 `history` | 显示历史
`sudo !!` | 使用 sudo 运行上一个命令 `sudo !!` | 使用 `sudo` 运行上一个命令
`shopt -s histverify` | 不要立即执行扩展结果 `shopt -s histverify` | 不要立即执行扩展结果
<!--rehype:className=left-align-->
### 表达式 ### 表达式
@ -694,6 +723,7 @@ Bash 历史
`!-n` | 展开第 `n` 个最近的命令 `!-n` | 展开第 `n` 个最近的命令
`!n` | 展开历史中的第 `n` 个命令 `!n` | 展开历史中的第 `n` 个命令
`!<command>` | 展开最近调用的命令 `<command>` `!<command>` | 展开最近调用的命令 `<command>`
<!--rehype:className=left-align-->
### 操作 ### 操作
@ -704,6 +734,7 @@ Bash 历史
`!!:gs/<FROM>/<TO>/` | 在最近的命令中将所有出现的 `<FROM>` 替换为 `<TO>` `!!:gs/<FROM>/<TO>/` | 在最近的命令中将所有出现的 `<FROM>` 替换为 `<TO>`
`!$:t` | 仅从最近命令的最后一个参数扩展基本名称 `!$:t` | 仅从最近命令的最后一个参数扩展基本名称
`!$:h` | 仅从最近命令的最后一个参数展开目录 `!$:h` | 仅从最近命令的最后一个参数展开目录
<!--rehype:className=left-align-->
`!!``!$` 可以替换为任何有效的扩展。 `!!``!$` 可以替换为任何有效的扩展。
@ -716,34 +747,35 @@ Bash 历史
`!$` | 从最近的命令中展开最后一个标记 `!$` | 从最近的命令中展开最后一个标记
`!!:n-m` | 从最近的命令扩展令牌范围 `!!:n-m` | 从最近的命令扩展令牌范围
`!!:n-$` | 从最近的命令中将第 `n` 个标记展开到最后 `!!:n-$` | 从最近的命令中将第 `n` 个标记展开到最后
<!--rehype:className=left-align-->
`!!` 可以替换为任何有效的扩展,即 `!cat``!-2``!42` 等。 `!!` 可以替换为任何有效的扩展,即 `!cat``!-2``!42` 等。
杂项 杂项
------------- ---
### 数值计算 ### 数值计算
```bash ```bash
$((a + 200)) # Add 200 to $a $((a + 200)) # $a 加 200
``` ```
```bash ```bash
$(($RANDOM%200)) # Random number 0..199 $(($RANDOM%200)) # 随机数 0..199
``` ```
### 子 shell ### 子 shell
```bash ```bash
(cd somedir; echo "I'm now in $PWD") (cd somedir; echo "I'm now in $PWD")
pwd # still in first directory pwd # 仍然在第一个目录
``` ```
### 检查命令 ### 检查命令
```bash ```bash
command -V cd command -V cd
#=> "cd is a function/alias/whatever" #=> "cd 是一个函数/别名/其他"
``` ```
### 重定向 ### 重定向