diff --git a/docs/bash.html b/docs/bash.html new file mode 100644 index 00000000..ceea2a66 --- /dev/null +++ b/docs/bash.html @@ -0,0 +1,1127 @@ + + +
+ +这是开始使用 linux bash shell 脚本的快速参考备忘单。
+#!/bin/bash
+VAR="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
+
+见:条件句
+echo {A,B}.js
+
+表示 | 描述 |
---|---|
{A,B} | 与 A B 相同 |
{A,B}.js | 与 A.js B.js 相同 |
{1..5} | 与 1 2 3 4 5 相同 |
见:大括号扩展
+# => I'm in /当前/的/路径
+echo "I'm in $(PWD)"
+# Same as:
+echo "I'm in `pwd`"
+
+见:命令替换
+代码 | 描述 |
---|---|
${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} | 从右边开始的子串 |
表示 | 描述 |
---|---|
${#FOO} | $FOO 的长度 |
表示 | 描述 |
---|---|
${FOO:-val} | $FOO ,如果未设置,则为 val |
${FOO:=val} | 如果未设置,则将 $FOO 设置为 val |
${FOO:+val} | val 如果设置了$FOO |
${FOO:?message} | 如果 $FOO 未设置,则显示消息并退出 |
echo ${food:-Cake} #=> $food or "Cake"
+
+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
+
+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
+
+见:参数扩展
+SRC="/path/to/foo.cpp"
+
+BASEPATH=${SRC##*/}
+echo $BASEPATH # => "foo.cpp"
+
+DIRPATH=${SRC%$BASEPATH}
+echo $DIRPATH # => "/path/to/"
+
+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
+
+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 |
Fruits=('Apple' 'Banana' 'Orange')
+for e in "${Fruits[@]}"; do
+ echo $e
+done
+
+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
+
+declare -A sounds
+
+sounds[dog]="bark"
+sounds[cow]="moo"
+sounds[bird]="tweet"
+sounds[wolf]="howl"
+
+echo ${sounds[dog]} # Dog's sound
+echo ${sounds[@]} # All values
+echo ${!sounds[@]} # All keys
+echo ${#sounds[@]} # Number of elements
+unset sounds[dog] # Delete dog
+
+for val in "${sounds[@]}"; do
+ echo $val
+done
+
+for key in "${!sounds[@]}"; do
+ echo $key
+done
+
+条件 | 描述 |
---|---|
[[ NUM -eq NUM ]] | 等于 |
[[ NUM -ne NUM ]] | 不等于 |
[[ NUM -lt NUM ]] | 少于 |
[[ NUM -le NUM ]] | 小于或等于 |
[[ NUM -gt NUM ]] | 大于 |
[[ NUM -ge NUM ]] | 大于或等于 |
(( 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"
+fi
+if [ "$1" = 'n' -o $2 -lt 0 ]; then
+ echo "no"
+fi
+
+for i in /etc/rc.*; do
+ echo $i
+done
+
+for ((i = 0 ; i < 100 ; i++)); do
+ echo $i
+done
+
+for i in {1..5}; do
+ echo "Welcome $i"
+done
+
+for i in {5..50..5}; do
+ echo "Welcome $i"
+done
+
+i=1
+while [[ $i -lt 4 ]]; do
+ echo "Number: $i"
+ ((i++))
+done
+
+i=3
+while [[ $i -gt 0 ]]; do
+ echo "Number: $i"
+ ((i--))
+done
+
+for number in $(seq 1 3); do
+ if [[ $number == 2 ]]; then
+ continue;
+ fi
+ echo "$number"
+done
+
+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
+
+count=0
+until [ $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 $line
+done
+
+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
+
+# 避免覆盖文件
+# (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
+
+命令 | 描述 |
---|---|
history | 显示历史 |
sudo !! | 使用 sudo 运行上一个命令 |
shopt -s histverify | 不要立即执行扩展结果 |
表达式 | 描述 |
---|---|
!$ | 展开最新命令的最后一个参数 |
!* | 展开最新命令的所有参数 |
!-n | 展开第 n 个最近的命令 |
!n | 展开历史中的第 n 个命令 |
!<command> | 展开最近调用的命令 <command> |
代码 | 描述 |
---|---|
!! | 再次执行最后一条命令 |
!!:s/<FROM>/<TO>/ | 在最近的命令中将第一次出现的 <FROM> 替换为 <TO> |
!!:gs/<FROM>/<TO>/ | 在最近的命令中将所有出现的 <FROM> 替换为 <TO> |
!$:t | 仅从最近命令的最后一个参数扩展基本名称 |
!$:h | 仅从最近命令的最后一个参数展开目录 |
!!
和 !$
可以替换为任何有效的扩展。
代码 | 描述 |
---|---|
!!:n | 仅扩展最近命令中的第 n 个标记(命令为 0 ;第一个参数为 1 ) |
!^ | 从最近的命令展开第一个参数 |
!$ | 从最近的命令中展开最后一个标记 |
!!:n-m | 从最近的命令扩展令牌范围 |
!!:n-$ | 从最近的命令中将第 n 个标记展开到最后 |
!!
可以替换为任何有效的扩展,即 !cat
、!-2
、!42
等。
$((a + 200)) # Add 200 to $a
+
+$(($RANDOM%200)) # Random number 0..199
+
+(cd somedir; echo "I'm now in $PWD")
+pwd # still in first directory
+
+command -V cd
+#=> "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 "$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 errtrace
+trap traperr ERR
+
+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; done
+if [[ "$1" == '--' ]]; then shift; fi
+
+if ping -c 1 google.com; then
+ echo "看来您的互联网连接正常"
+fi
+
+表达式 | 描述 |
---|---|
$? | 最后一个任务的退出状态 |
$! | 最后一个后台任务的 PID |
$$ | shell PID |
$0 | shell 脚本的文件名 |
见特殊参数。
+if grep -q 'foo' ~/.bash_history; then
+ echo "您过去似乎输入过“foo”"
+fi
+
+使用 \
转义这些特殊字符
cat <<END
+hello world
+END
+
+pwd # /home/user/foo
+cd bar/
+pwd # /home/user/foo/bar
+cd -
+pwd # /home/user/foo
+
+echo -n "Proceed? [y/n]: "
+read ans
+echo $ans
+
+read -n 1 ans # 只有一个字符
+
+git commit && git push
+git commit || echo "Commit failed"
+
+set -euo pipefail
+IFS=$'\n\t'
+
+
+args=("$@")
+args+=(foo)
+args+=(bar)
+echo "${args[@]}"
+
+将参数放入数组中,然后追加
+:- | - |
---|---|
shortcuts | 快捷键样式 |
wrap-text | 超出换行 |
show-header | 展示表头 |
:- | - |
---|---|
shortcuts | 快捷键样式 |
wrap-text | 超出换行 |
show-header | 展示表头 |
style-none | 隐藏 <ul> 列表样式 |
:- | - |
---|---|
<yel> | 黄色 |
<pur> | 紫色 |
<code> 或 `` | 绿色 |
:- | - |
---|---|
<yel> | |
<pur> | |
<code> 或 `` | 绿 色 |
这是一份 XPath 选择器备忘单,其中列出了常用的 XPath
定位方法和 CSS
选择器
XPath 即为 XML 路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的计算机语言。
类似路径
语法识别和导航 XML 文档中的节点在 Firefox 或 Chrome 控制台中测试:
+在 Firefox
或 Chrome
控制台中测试:
$x('/html/body')
$x('//h1')
$x('//h1')[0].innerText
@@ -197,7 +203,89 @@
Xpath CSS //h1/following-sibling::ul
h1 ~ ul //h1/following-sibling::ul[1]
h1 + ul //h1/following-sibling::[@id="id"]
h1 ~ #id
-
Xpath | CSS |
---|---|
nodename | 选择名称为 nodename 的所有节点 |
/ | 从根节点中选择 |
// | 从当前节点中选择文档中与选择匹配的节点,无论它们在哪里 |
. | 选择当前节点 |
.. | 选择当前节点的父节点 |
@ | 选择属性 |
Xpath | CSS |
---|---|
//h1[not(@id)] | h1:not([id]) |
//button[text()="Submit"] | 文字匹配 |
//button[contains(text(),"Go")] | 文本包含(子字符串) |
//product[@price > 2.50] | 算术 |
//ul[*] | 有孩子 |
//ul[li] | 有孩子(具体) |
//a[@name or @href] | 或逻辑 |
//a | //div | 联合(加入结果) |
Xpath | CSS |
---|---|
//ul/li/.. | $('ul > li').parent() |
//li/ancestor-or-self::section | $('li').closest('section') |
//a/@href | $('a').attr('href') |
//span/text() | $('span').text() |
Xpath | CSS |
---|---|
//h1[not(@id)] | h1:not([id]) |
//button[text()="Submit"] | 文字匹配 |
//button[contains(text(),"Go")] | 文本包含(子字符串) |
//product[@price > 2.50] | 算术 |
//ul[*] | 有孩子 |
//ul[li] | 有孩子(具体) |
//a[@name or @href] | 或逻辑 |
`//a | //div` |
运算符 | 说明 | 示例 |
---|---|---|
| | 计算两个节点集 | //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 |
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 |
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 | 选择当前节点之前的所有兄弟节点 |
您还可以使用其他轴。
为开发人员分享快速参考备忘清单(主要是方便自己),在看到 Reference 快速参考备忘单,感觉非常简单,造轮子使命感突然来了,造个中文版本的,为了方便自己的技术栈查阅,立马撸起来 :)。
如果您发现此处的备忘单不合适,您可以通过提交 PR 来修复它或提供更好的备忘清单,只针对【中文】用户。以下是开源天使提供的一些备忘清单和快速参考 :)。