From f65a82e176cfe0f28956c438820165b6f9b910d0 Mon Sep 17 00:00:00 2001 From: jaywcjlove <398188662@qq.com> Date: Mon, 3 Oct 2022 00:37:06 +0800 Subject: [PATCH] feat: add `bash.md` cheatsheet. --- README.md | 1 + docs/bash.md | 975 ++++++++++++++++++++++++++++++++++++++++ docs/quickreference.md | 7 +- docs/xpath.md | 84 +++- scripts/assets/bash.svg | 3 + scripts/style.css | 6 + 6 files changed, 1053 insertions(+), 23 deletions(-) create mode 100644 docs/bash.md create mode 100644 scripts/assets/bash.svg diff --git a/README.md b/README.md index 2e4690c5..15c56aaa 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Quick Reference ## 编程 +[Bash](./docs/bash.md) [Docker](./docs/docker.md) [Dockerfile](./docs/dockerfile.md) [JavaScript](./docs/javascript.md) diff --git a/docs/bash.md b/docs/bash.md new file mode 100644 index 00000000..19b4d218 --- /dev/null +++ b/docs/bash.md @@ -0,0 +1,975 @@ +Bash 备忘清单 +=== + +这是开始使用 linux bash shell 脚本的快速参考备忘单。 + +入门 +--------------- + +### hello.sh + +```bash +#!/bin/bash +VAR="world" +echo "Hello $VAR!" # => Hello world! +``` + +执行脚本 + +```shell +$ bash hello.sh +``` + +### 变量 + +```bash +NAME="John" +echo ${NAME} # => John (变量) +echo $NAME # => John (变量) +echo "$NAME" # => John (变量) +echo '$NAME' # => $NAME (确切的字符串) +echo "${NAME}!" # => John! (变量) +NAME = "John" # => Error (关于空间) +``` + +### 注释 + +```bash +# 这是一个内联 Bash 注释。 +``` + +```shell +: ' +这是一个 +非常整洁的评论 +在 bash +' +``` + +多行注释使用 `:'` 打开和 `'` 关闭 + +### 参数 + + +表示 | 描述 +:-|- +`$1` … `$9` | 参数 1 ... 9 +`$0` | 脚本本身的名称 +`$1` | 第一个论点 +`${10}` | 位置参数 10 +`$#` | 参数数量 +`$$` | shell 的进程 id +`$*` | 所有论据 +`$@` | 所有参数,从第一个开始 +`$-` | 当前选项 +`$_` | 上一个命令的最后一个参数 + +见:[特殊参数](http://wiki.bash-hackers.org/syntax/shellvars#special_parameters_and_shell_variables) + + +### 函数 + +```bash +get_name() { + echo "John" +} +echo "You are $(get_name)" +``` + +见:[函数](#bash-函数) + +### 条件句 + +```bash +if [[ -z "$string" ]]; then + echo "String is empty" +elif [[ -n "$string" ]]; then + echo "String is not empty" +fi +``` + +见:[条件句](#bash-条件句) + +### 大括号扩展 + +```shell +echo {A,B}.js +``` + +--- + +表示 | 描述 +:-|- +`{A,B}` | 与 `A B` 相同 +`{A,B}.js` | 与 `A.js B.js` 相同 +`{1..5}` | 与 `1 2 3 4 5` 相同 + +见:[大括号扩展](http://wiki.bash-hackers.org/syntax/expansion/brace) + +### Shell 执行 + +```bash +# => I'm in /当前/的/路径 +echo "I'm in $(PWD)" +# Same as: +echo "I'm in `pwd`" +``` + +见:[命令替换](http://wiki.bash-hackers.org/syntax/expansion/cmdsubst) + +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 + +```bash +echo ${food:-Cake} #=> $food or "Cake" +``` + +```bash +STR="/path/to/foo.cpp" +echo ${STR%.cpp} # /path/to/foo +echo ${STR%.cpp}.o # /path/to/foo.o +echo ${STR%/*} # /path/to +echo ${STR##*.} # cpp (extension) +echo ${STR##*/} # foo.cpp (basepath) +echo ${STR#*/} # path/to/foo.cpp +echo ${STR##*/} # foo.cpp +echo ${STR/foo/bar} # /path/to/bar.cpp +``` + +### 切片 Slicing + +```bash +name="John" +echo ${name} # => John +echo ${name:0:2} # => Jo +echo ${name::2} # => Jo +echo ${name::-1} # => Joh +echo ${name:(-1)} # => n +echo ${name:(-2)} # => hn +echo ${name:(-2):2} # => hn + +length=2 +echo ${name:0:length} # => Jo +``` + +见:[参数扩展](http://wiki.bash-hackers.org/syntax/pe) + +### 基本路径和目录路径 + +```bash +SRC="/path/to/foo.cpp" +``` + +```bash +BASEPATH=${SRC##*/} +echo $BASEPATH # => "foo.cpp" + +DIRPATH=${SRC%$BASEPATH} +echo $DIRPATH # => "/path/to/" +``` + +### Transform + +```bash +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 world +echo "${ARR[@]^}" # => Hello World +``` + +Bash 数组 +------ + +### 定义数组 + +```bash +Fruits=('Apple' 'Banana' 'Orange') + +Fruits[0]="Apple" +Fruits[1]="Banana" +Fruits[2]="Orange" + +ARRAY1=(foo{1..2}) # => foo1 foo2 +ARRAY2=({A..D}) # => A B C D + +# 合并 => foo1 foo2 A B C D +ARRAY3=(${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 + +```bash +Fruits=('Apple' 'Banana' 'Orange') +for e in "${Fruits[@]}"; do + echo $e +done +``` +#### With index +```bash +for i in "${!Fruits[@]}"; do + printf "%s\t%s\n" "$i" "${Fruits[$i]}" +done +``` + +### 操作 + + +```bash +Fruits=("${Fruits[@]}" "Watermelon") # 推 +Fruits+=('Watermelon') # 也推 +Fruits=( ${Fruits[@]/Ap*/} ) # 通过正则表达式匹配删除 +unset Fruits[2] # 删除一项 +Fruits=("${Fruits[@]}") # 复制 +Fruits=("${Fruits[@]}" "${Veggies[@]}") # 连接 +lines=(`cat "logfile"`) # 从文件中读取 +``` + +### 数组作为参数 + +```bash +function extract() +{ + local -n myarray=$1 + local idx=$2 + echo "${myarray[$idx]}" +} +Fruits=('Apple' 'Banana' 'Orange') +extract Fruits 2 # => Orangle +``` + +Bash 字典 +------------ + +### 定义 + +```bash +declare -A sounds +``` + +```bash +sounds[dog]="bark" +sounds[cow]="moo" +sounds[bird]="tweet" +sounds[wolf]="howl" +``` + +### 使用字典 + +```bash +echo ${sounds[dog]} # Dog's sound +echo ${sounds[@]} # All values +echo ${!sounds[@]} # All keys +echo ${#sounds[@]} # Number of elements +unset sounds[dog] # Delete dog +``` + +### 迭代 + +```bash +for val in "${sounds[@]}"; do + echo $val +done +``` + +--- + +```bash +for key in "${!sounds[@]}"; do + echo $key +done +``` + +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 ]]` | 正则表达式 + +### 例子 + + +#### 字符串 + +```bash +if [[ -z "$string" ]]; then + echo "String is empty" +elif [[ -n "$string" ]]; then + echo "String is not empty" +else + echo "This never happens" +fi +``` + +#### 组合 + +```bash +if [[ X && Y ]]; then + ... +fi +``` + +#### 相等 + +```bash +if [[ "$A" == "$B" ]]; then + ... +fi +``` + +#### 正则表达式 + +```bash +if [[ '1. abc' =~ ([a-z]+) ]]; then + echo ${BASH_REMATCH[1]} +fi +``` + +#### 更小 + +```bash +if (( $a < $b )); then + echo "$a is smaller than $b" +fi +``` + +#### 存在 + +```bash +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 + +### 逻辑和,或 + +```bash +if [ "$1" = 'y' -a $2 -gt 0 ]; then + echo "yes" +fi +if [ "$1" = 'n' -o $2 -lt 0 ]; then + echo "no" +fi +``` + +Bash 循环 +----- + +### 基本 for 循环 + +```bash +for i in /etc/rc.*; do + echo $i +done +``` + +### 类似 C 的 for 循环 + +```bash +for ((i = 0 ; i < 100 ; i++)); do + echo $i +done +``` + +### 范围 + + +```bash +for i in {1..5}; do + echo "Welcome $i" +done +``` + +#### 具有步长 + +```bash +for i in {5..50..5}; do + echo "Welcome $i" +done +``` + +### 自动递增 + +```bash +i=1 +while [[ $i -lt 4 ]]; do + echo "Number: $i" + ((i++)) +done +``` + +### 自动递增 + +```bash +i=3 +while [[ $i -gt 0 ]]; do + echo "Number: $i" + ((i--)) +done +``` + +### Continue + +```bash {data=3,5} +for number in $(seq 1 3); do + if [[ $number == 2 ]]; then + continue; + fi + echo "$number" +done +``` + +### Break + +```bash +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 + +```bash +count=0 +until [ $count -gt 10 ]; do + echo "$count" + ((count++)) +done +``` + +### 永远 + +```bash +while true; do + # here is some code. +done +``` + +### 永远(简写) + +```bash +while :; do + # here is some code. +done +``` + + +### 正在读取行 + +```bash +cat file.txt | while read line; do + echo $line +done +``` + +Bash 函数 +--------- + +### 定义函数 + +```bash +myfunc() { + echo "hello $1" +} +``` + +```bash +# 同上(替代语法) +function myfunc() { + echo "hello $1" +} +``` + +```bash +myfunc "John" +``` + +### 返回值 + +```bash +myfunc() { + local myresult='some value' + echo $myresult +} +``` + +```bash +result="$(myfunc)" +``` + +### 正在引发错误 + +```bash +myfunc() { + return 1 +} +``` + +```bash +if myfunc; then + echo "success" +else + echo "failure" +fi +``` + +Bash 选项 +------- + + +### 选项 + +```bash +# 避免覆盖文件 +# (echo "hi" > foo) +set -o noclobber + +# 用于出错时退出 +# 避免级联错误 +set -o errexit + +# 揭示隐藏的失败 +set -o pipefail + +# 公开未设置的变量 +set -o nounset +``` + +### 全局选项 + +```bash +# 不匹配的 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` 个命令 +`!` | 展开最近调用的命令 `` + +### 操作 + +代码 | 描述 +:- | - +`!!` | 再次执行最后一条命令 +`!!:s///` | 在最近的命令中将第一次出现的 `` 替换为 `` +`!!:gs///` | 在最近的命令中将所有出现的 `` 替换为 `` +`!$:t` | 仅从最近命令的最后一个参数扩展基本名称 +`!$:h` | 仅从最近命令的最后一个参数展开目录 + +`!!` 和 `!$` 可以替换为任何有效的扩展。 + +### 切片 Slices + +代码 | 描述 +:- | - +`!!:n` | 仅扩展最近命令中的第 `n` 个标记(命令为 `0`;第一个参数为 `1`) +`!^` | 从最近的命令展开第一个参数 +`!$` | 从最近的命令中展开最后一个标记 +`!!:n-m` | 从最近的命令扩展令牌范围 +`!!:n-$` | 从最近的命令中将第 `n` 个标记展开到最后 + +`!!` 可以替换为任何有效的扩展,即 `!cat`、`!-2`、`!42` 等。 + + +各种各样的 +------------- + +### 数值计算 + +```bash +$((a + 200)) # Add 200 to $a +``` + +```bash +$(($RANDOM%200)) # Random number 0..199 +``` + +### 子 shell + +```bash +(cd somedir; echo "I'm now in $PWD") +pwd # still in first directory +``` + + +### 检查命令 + +```bash +command -V cd +#=> "cd is a function/alias/whatever" +``` + +### 重定向 + + +```bash +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) +``` + +```bash +python hello.py < foo.txt # 将 foo.txt 提供给 python 的标准输入 +``` + + +### 来源相对 + +```bash +source "${0%/*}/../share/foo.sh" +``` + +### 脚本目录 + +```bash +DIR="${0%/*}" +``` + +### Case/switch + +```bash +case "$1" in + start | up) + vagrant up + ;; + *) + echo "Usage: $0 {start|stop|ssh}" + ;; +esac +``` + + +### 陷阱错误 + + +```bash +trap 'echo Error at about $LINENO' ERR +``` + +或者 + +```bash +traperr() { + echo "ERROR: ${BASH_SOURCE[1]} at about ${BASH_LINENO[0]}" +} +set -o errtrace +trap traperr ERR +``` + +### printf + +```bash +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" +``` + +### 获取选项 + + +```bash +while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in + -V | --version ) + echo $version + exit + ;; + -s | --string ) + shift; string=$1 + ;; + -f | --flag ) + flag=1 + ;; +esac; shift; done +if [[ "$1" == '--' ]]; then shift; fi +``` + +### 检查命令的结果 + + +```bash +if ping -c 1 google.com; then + echo "看来您的互联网连接正常" +fi +``` + +### 特殊变量 + + +表达式 | 描述 +:- | - +`$?` | 最后一个任务的退出状态 +`$!` | 最后一个后台任务的 PID +`$$` | shell PID +`$0` | shell 脚本的文件名 + +见[特殊参数](http://wiki.bash-hackers.org/syntax/shellvars#special_parameters_and_shell_variables)。 + + +### grep 检查 + + +```bash +if grep -q 'foo' ~/.bash_history; then + echo "您过去似乎输入过“foo”" +fi +``` + + +### 反斜杠转义 + + +-   +- \! +- \" +- \# +- \& +- \' +- \( +- \) +- \, +- \; +- \< +- \> +- \[ +- \| +- \\ +- \] +- \^ +- \{ +- \} +- \` +- \$ +- \* +- \? + + +使用 `\` 转义这些特殊字符 + +### Heredoc + +```sh +cat <` 列表样式 ### 颜色标签 :- | - :- | - -`` | 黄色 -`` | 紫色 -`` 或 \`\` | 绿色 +`` | 黄色 +`` | 紫色 +`` 或 \`\` | 绿`色` diff --git a/docs/xpath.md b/docs/xpath.md index fb9b156a..015ed745 100644 --- a/docs/xpath.md +++ b/docs/xpath.md @@ -7,12 +7,18 @@ XPath 选择器 -------- ### 入门 + XPath 即为 XML 路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的计算机语言。 - [Xpath test bed](http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm) _(whitebeam.org)_ +- XPath 代表 XML 路径语言 +- XPath 使用 `类似路径` 语法识别和导航 XML 文档中的节点 +- XPath 包含超过 200 个内置函数 +- XPath 是 XSLT 标准中的主要元素 +- XPath 是 W3C 推荐的 -在 Firefox 或 Chrome 控制台中测试: +在 `Firefox` 或 `Chrome` 控制台中测试: ```js $x('/html/body') @@ -71,17 +77,20 @@ $x('//a[text()="XPath"]')[0].click() | `//h1/following-sibling::[@id="id"]` | h1 ~ #id | -### jQuery +### 最有用的路径表达式 | Xpath | CSS | |----------------------------------|----------------------------| -| `//ul/li/..` | $('ul > li').parent() | -| `//li/ancestor-or-self::section` | $('li').closest('section') | -| `//a/@href` | $('a').attr('href') | -| `//span/text()` | $('span').text() | +`nodename` | 选择名称为 `nodename` 的所有节点 +`/` | 从根节点中选择 +`//` | 从当前节点中选择文档中与选择匹配的节点,无论它们在哪里 +`.` | 选择当前节点 +`..` | 选择当前节点的父节点 +`@` | 选择属性 ### 杂项选择器 + | Xpath | CSS | |-----------------------------------|---------------------------| @@ -92,9 +101,44 @@ $x('//a[text()="XPath"]')[0].click() | `//ul[*]` | 有孩子 | | `//ul[li]` | 有孩子(具体) | | `//a[@name or @href]` | 或逻辑 | -| `//a | //div` | 联合(加入结果) | +| `//a \| //div` | 联合(加入结果) | +### jQuery + + +| Xpath | CSS | +|----------------------------------|----------------------------| +| `//ul/li/..` | $('ul > li').parent() | +| `//li/ancestor-or-self::section` | $('li').closest('section') | +| `//a/@href` | $('a').attr('href') | +| `//span/text()` | $('span').text() | + + +### 运算符 + + + +运算符 | 说明 | 示例 +:- | - | - +`\|` | 计算两个节点集 | `//book \| //cd` +`+` | 添加 | `6 + 4` +`-` | 减法 | `6 - 4` +`*` | 乘法 | `6 * 4` +`div` | 分配 | `8 div 4` +`=` | 平等的 | `price=9.80` +`!=` | 不相等 | `price!=9.80` +`<` | 小于 | `price<9.80` +`<=` | 小于或等于 | `price<=9.80` +`>` | 大于 | `price>9.80` +`>=` | 大于或等于 | `price>=9.80` +`or` | 或者 | `price=9.80` or `price=9.70` +`and` | 和 | `price>9.00` and `price<9.90` +`mod` | 模数(除法余数) | `5` mod `2` + + + + XPath 表达式 ----------- @@ -311,19 +355,19 @@ XPath Axes | Axis | Abbrev | Notes | |--------------------|--------|-------| -| `ancestor` | | | -| `ancestor-or-self` | | | -| `attribute` | `@` | `@href` 是 `attribute::href` 的缩写 | -| `child` | | `div` 是 `child::div` 的缩写 | -| `descendant` | | | -| `descendant-or-self` | `//` | `//` 是 `/descendant-or-self::node()/`的缩写 | -| `namespace` | | | -| `self` | `.` | `.` 是 `self::node()` 的缩写 | -| `parent` | `..` | `..` 是 `parent::node()` 的缩写 | -| `following` | | | -| `following-sibling` | | | -| `preceding` | | | -| `preceding-sibling` | | | +`ancestor` | | 选择当前节点的所有祖先(父母、祖父母等) +`ancestor-or-self` | | 选择当前节点所有祖先(父、祖父等)和当前节点本身 +`attribute` | `@` | `@href` 是 `attribute::href` 的缩写 +`child` | | `div` 是 `child::div` 的缩写 +`descendant` | | 选择当前节点的所有后代(子、孙等) +`descendant-or-self` | `//` | `//` 是 `/descendant-or-self::node()/`的缩写 选择当前节点和当前节点本身的所有后代(子、孙等) +`namespace` | | 选择当前节点的所有命名空间节点 +`self` | `.` | `.` 是 `self::node()` 的缩写,选择当前节点 +`parent` | `..` | `..` 是 `parent::node()` 的缩写,选择当前节点的父节点 +`following` | | 选择文档中当前节点结束标记之后的所有内容 +`following-sibling` | | 选择当前节点之后的所有兄弟节点 +`preceding` | | 选择文档中出现在当前节点之前的所有节点,除了祖先、属性节点和命名空间节点 +`preceding-sibling` | | 选择当前节点之前的所有兄弟节点 您还可以使用其他轴。 diff --git a/scripts/assets/bash.svg b/scripts/assets/bash.svg new file mode 100644 index 00000000..40db03bf --- /dev/null +++ b/scripts/assets/bash.svg @@ -0,0 +1,3 @@ + + + diff --git a/scripts/style.css b/scripts/style.css index d5c60ca9..93f610dd 100644 --- a/scripts/style.css +++ b/scripts/style.css @@ -543,6 +543,12 @@ body:not(.home) .h2wrap > h2 a::after { grid-template-columns: repeat(1,minmax(0,1fr)); } +.h3wrap > .wrap-body ul:not(:last-child), +.h3wrap > .wrap-body ol, +.h3wrap > .wrap-body dl { + margin-bottom: 0; +} + .h2wrap-body ul li, .h2wrap-body ol li, .h2wrap-body dl li {