删除重复的数组元素
创建临时关联数组。设置关联数组
值并发生重复赋值时,bash会覆盖该键。这
允许我们有效地删除数组重复。
CAVEAT:需要bash4+
示例功能:
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
随机数组元素
示例功能:
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
循环一个数组
每次printf调用时,都会打印下一个数组元素。当
打印到达最后一个数组元素时,它
再次从第一个元素开始。
arr=(a b c d) cycle() { printf '%s ' "${arr[${i:=0}]}" ((i=i>=${#arr[@]}-1?0:++i))
}
在两个值之间切换
这与上面的工作方式相同,这只是一个不同的用例。
arr=(true false) cycle() { printf '%s ' "${arr[${i:=0}]}" ((i=i>=${#arr[@]}-1?0:++i))
}
LOOPS
循环一系列数字
替代seq。
# Loop from 0-100 (no variable support). for i in {0..100}; do printf '%s\n' "$i" done
循环遍历可变数字范围
替代seq。
# Loop from 0-VAR. VAR=50 for ((i=0;i<=VAR;i++)); do printf '%s\n' "$i" done
循环数组
arr=(apples oranges tomatoes) # Just elements. for element in "${arr[@]}"; do printf '%s\n' "$element" done
循环遍历带索引的数组
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
循环遍历文件的内容
while read -r line; do printf '%s\n' "$line" done < "file"
循环遍历文件和目录
不要用ls。
# 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
文件处理
CAVEAT: bash在版本中不能正确处理二进制数据< 4.4。
将文件读取为字符串
替代cat命令。
file_data="$(<"file")"
将文件读取到数组(按行)
替代cat命令。
# Bash <4 IFS=$'\n' read -d "" -ra file_data < "file" # Bash 4+ mapfile -t file_data < "file"
获取文件的前N行
替代head命令。
CAVEAT:需要bash4+
示例功能:
head() { # Usage: head "n" "file" mapfile -tn "$1" line < "$2" printf '%s\n' "${line[@]}" }
用法示例:
$ head 2 ~/.bashrc # Prompt PS1='➜ ' $ head 1 ~/.bashrc # Prompt
获取文件的最后N行
替代tail命令。
CAVEAT:需要bash4+
示例功能:
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
获取文件中的行数
替代wc -l。
示例函数(bash 4):
lines() { # Usage: lines "file" mapfile -tn 0 lines < "$1" printf '%s\n' "${#lines[@]}" }
示例函数(bash 3):
此方法使用的内存少于mapfile方法,并在bash3中工作,但对于较大的文件,它的速度较慢。
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
计算目录中的文件或目录
这是通过将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
创建一个空文件
替代touch。
# Shortest. >file # Longer alternatives: :>file echo -n >file printf '' >file
提取两个标记之间的线条
示例功能:
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...
文件路径
获取文件路径的目录名称
替代dirname命令。
示例功能:
dirname() { # Usage: dirname "path" printf '%s\n' "${1%/*}/" }
用法示例:
$ dirname ~/Pictures/Wallpapers/1.jpg
/home/black/Pictures/Wallpapers/
$ dirname ~/Pictures/Downloads/ /home/black/Pictures/
获取文件路径的基本名称
替代basename命令。
示例功能:
basename() { # Usage: basename "path" : "${1%/}" printf '%s\n' "${_##*/}" }
用法示例:
$ basename ~/Pictures/Wallpapers/1.jpg 1.jpg
$ basename ~/Pictures/Downloads/
Downloads
变量
使用变量分配和访问变量
$ 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
或者,在bash4.3+上:
$ hello_world="value" $ var="world" # Declare a nameref. $ declare -n ref=hello_$var $ printf '%s\n' "$ref" value
根据另一个变量命名变量
$ var="world" $ declare "hello_$var=value" $ printf '%s\n' "$hello_world" value
ESCAPE序列
与流行的看法相反,使用原始逃逸序列没有问题。使用tput与手动打印相同的ANSI序列的摘要。更糟糕的是,tput实际上并不便携。有许多tput变体,每个变体都有不同的命令和语法(尝试tput setaf 3使用FreeBSD系统)。原始序列很好。
文字颜色
注意:需要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 |
文字属性
序列 | 它有什么作用? |
\e[m | 重置文本格式和颜色。 |
\e[1m | 粗体。 |
\e[2m | 微弱的文字。 |
\e[3m | 斜体文字。 |
\e[4m | 下划线文字。 |
\e[5m | 慢慢眨眼。 |
\e[7m | 交换前景色和背景色。 |
光标移动
序列 | 它有什么作用? | 值 |
\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 | 恢复光标位置。 |
删除文本
序列 | 它有什么作用? |
\e[K | 从光标位置删除到行尾。 |
\e[1K | 从光标位置删除到行首。 |
\e[2K | 擦除整个当前行。 |
\e[J | 从当前行删除到屏幕底部。 |
\e[1J | 从当前行删除到屏幕顶部。 |
\e[2J | 清除屏幕。 |
\e[2J\e[H | 清除屏幕并将光标移动到0,0。 |
参数扩展
间接
参数 | 它有什么作用? |
${!VAR} | 根据值访问变量VAR。 |
${!VAR*} | 展开为IFS以VAR。开头的变量名称的分隔列表。 |
${!VAR@} | 展开为IFS以VAR。开头的变量名称的分隔列表。如果是双引号,则每个变量名称都会扩展为单独的单词。 |
替换
参数 | 它有什么作用? |
${VAR#PATTERN} | 从字符串的开头删除模式的最短匹配。 |
${VAR##PATTERN} | 从字符串的开头删除模式的最长匹配。 |
${VAR%PATTERN} | 从字符串末尾删除模式的最短匹配。 |
${VAR%%PATTERN} | 从字符串末尾删除模式的最长匹配。 |
${VAR/PATTERN/REPLACE} | 用字符串替换第一个匹配。 |
${VAR//PATTERN/REPLACE} | 用字符串替换所有匹配项。 |
${VAR/PATTERN} | 删除第一场比赛。 |
${VAR//PATTERN} | 删除所有比赛。 |
长度
参数 | 它有什么作用? |
${#VAR} | 字符变量的长度。 |
${#ARR[@]} | 元素中的数组长度。 |
扩张
参数 | 它有什么作用? | |
${VAR:OFFSET} | N从变量中删除第一个字符。 | |
${VAR:OFFSET:LENGTH} | 从N字符到N字符获取子字符串。 | |
(${VAR:10:10}:从char 10到char 获取子字符串20) | ||
${VAR:: OFFSET} | N从变量中获取第一个字符。 | |
${VAR:: -OFFSET} | N从变量中删除最后一个字符。 | |
${VAR: -OFFSET} | N从变量中获取最后一个字符。 | |
${VAR:OFFSET:-OFFSET} | 削减第一个N字符和最后一个N字符。 | bash 4.2+ |
案例修改
参数 | 它有什么作用? | 警告 |
${VAR^} | 大写第一个字符。 | bash 4+ |
${VAR^^} | 大写所有字符。 | bash 4+ |
${VAR,} | 小写第一个字符。 | bash 4+ |
${VAR,,} | 小写所有字符。 | bash 4+ |
默认值
参数 | 它有什么作用? |
${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?STRING} | 如果未设置则显示错误。 |
BRACE EXPANSION
范围
# Syntax: {<START>..<END>} # Print numbers 1-100. echo {1..100} # Print range of floats. echo 1.{1..9} # Print chars a-z. echo {a..z} echo {A..Z} # Nesting. echo {A..Z}{0..9} # Print zero-padded numbers. # CAVEAT: bash 4+ echo {01..100} # Change increment amount. # Syntax: {<START>..<END>..<INCREMENT>} # CAVEAT: bash 4+ echo {1..10..2} # Increment by 2.
字符串列表
echo {apples,oranges,pears,grapes} # Example Usage: # Remove dirs Movies, Music and ISOS from ~/Downloads/. rm -rf ~/Downloads/{Movies,Music,ISOS}
有条件的表达
文件条件
表达 | 值 | 它有什么作用? |
-a | file | 如果文件存在。 |
-b | file | 如果文件存在并且是块特殊文件。 |
-c | file | 如果文件存在并且是字符特殊文件。 |
-d | file | 如果文件存在且是目录。 |
-e | file | 如果文件存在。 |
-f | file | 如果文件存在且是常规文件。 |
-g | file | 如果文件存在且其set-group-id位已设置。 |
-h | file | 如果文件存在并且是符号链接。 |
-k | file | 如果文件存在且其粘滞位已设置 |
-p | file | 如果文件存在并且是命名管道(FIFO)。 |
-r | file | 如果文件存在且可读。 |
-s | file | 如果文件存在且其大小大于零。 |
-t | fd | 如果文件描述符是打开的并且引用了终端。 |
-u | file | 如果文件存在且其set-user-id位已设置。 |
-w | file | 如果文件存在且可写。 |
-x | file | 如果文件存在且可执行。 |
-G | file | 如果文件存在且由有效组ID拥有。 |
-L | file | 如果文件存在并且是符号链接。 |
-N | file | 如果文件存在且自上次读取后已被修改。 |
-O | file | 如果文件存在并且由有效用户ID拥有。 |
-S | file | 如果文件存在且是套接字。 |
文件比较
表达 | 它有什么作用? |
file -ef file2 | 如果两个文件都引用相同的inode和设备编号。 |
file -nt file2 | 如果file比file2(使用修改时间)更新或file存在file2而不存在。 |
file -ot file2 | 如果file早于file2(使用修改时间)或file2存在file而不存在。 |
可变条件
表达 | 值 | 它有什么作用? |
-o | opt | 如果启用了shell选项。 |
-v | var | 如果变量具有指定的值。 |
-R | var | 如果variable是名称引用。 |
-z | var | 如果字符串的长度为零。 |
-n | var | 如果字符串的长度不为零。 |
变量比较
表达 | 它有什么作用? |
var = var2 | 等于。 |
var == var2 | 等于(同义词=)。 |
var != var2 | 不等于。 |
var < var2 | 小于(以ASCII字母顺序排列。) |
var > var2 | 大于(以ASCII字母顺序排列。) |
算术运算符
分配
运营商 | 它有什么作用? |
= | 初始化或更改变量的值。 |
算术
运营商 | 它有什么作用? |
+ | 加成 |
- | 减法 |
* | 乘法 |
/ | 师 |
** | 幂 |
% | 模 |
+= | 加 - 等于(增加变量。) |
-= | 减去等于(减少变量。) |
*= | 时间相等(乘以变量。) |
/= | Slash-Equal(除以变量。) |
%= | Mod-Equal(除去变量的剩余部分。) |
按位
运营商 | 它有什么作用? | |
<< | 按位左移 | |
<<= | 左移平等 | |
>> | 按位右移 | |
>>= | 右移平等 | |
& | 按位AND | |
&= | 按位AND-Equal | |
` | ` | 按位OR |
` | =` | 按位OR-等于 |
~ | 按位NOT | |
^ | 按位异或 | |
^= | 按位XOR-Equal |
合乎逻辑
运营商 | 它有什么作用? | ||
! | 不 | ||
&& | 和 | ||
` | ` | 要么 |
杂
运营商 | 它有什么作用? | 例 |
, | 逗号分隔符 | ((a=1,b=2,c=3)) |
算术
设置变量的语法更简单
# Simple math ((var=1+2)) # Decrement/Increment variable ((var++))
((var--))
((var+=1))
((var-=1)) # Using variables ((var=var2*arr[2]))
三元测试
# Set the value of var to var2 if var2 is greater than var. # var: variable to set. # var2>var: Condition to test. # ?var2: If the test succeeds. # :var: If the test fails. ((var=var2>var?var2:var))
TRAPS
陷阱允许脚本在各种信号上执行代码。在pxltrm(用bash编写的像素艺术编辑器)中,陷阱用于在窗口大小调整时重绘用户界面。另一个用例是在脚本退出时清理临时文件。
应该在脚本开头附近添加陷阱,以便捕获任何早期错误。
注意:有关信号的完整列表,请参阅trap -l。
在脚本退出时做一些事情
# Clear screen on script exit. trap 'printf \\e[2J\\e[H\\e[m' EXIT
忽略终端中断(CTRL + C,SIGINT)
trap '' INT
对窗口调整大小做出反应
# Call a function on window resize. trap 'code_here' SIGWINCH
在每个命令之前做点什么
trap 'code_here' DEBUG
当shell函数或源文件完成执行时执行某些操作
trap 'code_here' RETURN
性能
禁用Unicode
如果不需要unicode,则可以禁用它以提高性能。结果可能会有所不同,但是neofetch和其他程序有明显改善。
# Disable unicode. LC_ALL=C LANG=C
已过时的语法
家当
用#!/usr/bin/env bash而不是#!/bin/bash。
前者搜索用户PATH以查找bash二进制文件。
后者假设它始终安装/bin/可能导致问题。
# Right: #!/usr/bin/env bash # Wrong: #!/bin/bash
命令替换
用$()而不是。
# Right. var="$(command)" # Wrong. var=`command` # $() can easily be nested whereas `` cannot. var="$(command "$(command)")"
功能声明
不要使用function关键字,它会降低与旧版本的兼容性bash。
# Right. do_something() { # ... } # Wrong. function do_something() { # ... }
内部变量
获取bash二进制文件的位置
"$BASH"
获取当前正在运行的bash进程的版本
# As a string. "$BASH_VERSION" # As an array. "${BASH_VERSINFO[@]}"
打开用户首选的文本编辑器
"$EDITOR" "$file" # NOTE: This variable may be empty, set a fallback value. "${EDITOR:-vi}" "$file"
获取当前函数的名称
# Current function. "${FUNCNAME[0]}" # Parent function. "${FUNCNAME[1]}" # So on and so forth. "${FUNCNAME[2]}" "${FUNCNAME[3]}" # All functions including parents. "${FUNCNAME[@]}"
获取系统的主机名
"$HOSTNAME" # NOTE: This variable may be empty. # Optionally set a fallback to the hostname command. "${HOSTNAME:-$(hostname)}"
获取操作系统的体系结构
"$HOSTTYPE"
获取操作系统/内核的名称
这可用于为不同的操作系统添加条件支持,
而无需调用uname。
"$OSTYPE"
获取当前的工作目录
这是pwd内置的替代品。
"$PWD"
获取脚本运行的秒数
"$SECONDS"
获取伪随机整数
每次$RANDOM使用时,之间的不同整数0及32767被返回。此变量不应用于与安全性相关的任何内容(包括加密密钥等)。
"$RANDOM"
有关终端的信息
获取行和列中的终端大小(来自脚本)
在纯bash中编写脚本和stty/ tput无法
调用时,这很方便。
示例功能:
get_term_size() { # Usage: get_term_size # (:;:) is a micro sleep to ensure the variables are # exported immediately. shopt -s checkwinsize; (:;:) printf '%s\n' "$LINES $COLUMNS" }
用法示例:
# Output: LINES COLUMNS $ get_term_size 15 55
以像素为单位获取终端大小
CAVEAT:这在某些终端仿真器中不起作用。
示例功能:
get_window_size() { # Usage: get_window_size printf '%b' "${TMUX:+\\ePtmux;\\e}\\e[14t${TMUX:+\\e\\\\}" IFS=';t' read -d t -t 0.05 -sra term_size printf '%s\n' "${term_size[1]}x${term_size[2]}" }
用法示例:
# Output: WIDTHxHEIGHT $ get_window_size 1200x800 # Output (fail): $ get_window_size
x
获取当前光标位置
在纯bash中创建TUI时,这很有用。
示例功能:
get_cursor_pos() { # Usage: get_cursor_pos IFS='[;' read -p $'\e[6n' -d R -rs _ y x _ printf '%s\n' "$x $y" }
用法示例:
# Output: X Y $ get_cursor_pos 1 8
转换
将十六进制颜色转换为RGB
示例功能:
hex_to_rgb() { # Usage: hex_to_rgb "#FFFFFF" # hex_to_rgb "000000" : "${1/\#}" ((r=16#${_:0:2},g=16#${_:2:2},b=16#${_:4:2})) printf '%s\n' "$r $g $b" }
用法示例:
$ hex_to_rgb "#FFFFFF" 255 255 255
将RGB颜色转换为十六进制
示例功能:
rgb_to_hex() { # Usage: rgb_to_hex "r" "g" "b" printf '#%02x%02x%02x\n' "$1" "$2" "$3" }
用法示例:
$ rgb_to_hex "255" "255" "255" #FFFFFF
CODE GOLF
更短的for循环语法
# Tiny C Style. for((;i++<10;)){ echo "$i";} # Undocumented method. for i in {1..10};{ echo "$i";} # Expansion. for i in {1..10}; do echo "$i"; done # C Style. for((i=0;i<=10;i++)); do echo "$i"; done
更短的无限循环
# Normal method while :; do echo hi; done # Shorter for((;;)){ echo hi;}
更短的功能声明
# Normal method f(){ echo hi;} # Using a subshell f()(echo hi) # Using arithmetic # This can be used to assign integer values. # Example: f a=1 # f a++ f()(($1)) # Using tests, loops etc. # NOTE: ‘while’, ‘until’, ‘case’, ‘(())’, ‘[[]]’ can also be used. f()if true; then echo "$1"; fi f()for i in "$@"; do echo "$i"; done
if语法更短
# One line
# Note: The 3rd statement may run when the 1st is true [[ $var == hello ]] && echo hi || echo bye [[ $var == hello ]] && { echo hi; echo there; } || echo bye
# Multi line (no else, single statement)
# Note: The exit status may not be the same as with an if statement [[ $var == hello ]] &&
echo hi
# Multi line (no else) [[ $var == hello ]] && {
echo hi
# ...
}
case设置变量的简单语句
在:内置的可以用来避免重复variable=在一个case语句。该$_变量存储的最后一个命令的最后一个参数。:总是成功,所以它可以用来存储变量值。
# Modified snippet from Neofetch. case "$OSTYPE" in "darwin"*)
: "MacOS" ;; "linux"*)
: "Linux" ;;
*"bsd"* | "dragonfly" | "bitrig")
: "BSD" ;; "cygwin" | "msys" | "win32")
: "Windows" ;;
*) printf '%s\n' "Unknown OS detected, aborting..." >&2 exit 1
;; esac # Finally, set the variable. os="$_"
其他
使用read作为替代的sleep命令
令人惊讶的是,sleep是一个外部命令而不是bash内置命令。
CAVEAT:需要bash4+
示例功能:
read_sleep() { # Usage: sleep 1 # sleep 0.2 read -rst "${1:-1}" -N 999
}
用法示例:
read_sleep 1 read_sleep 0.1 read_sleep 30
检查程序是否在用户的PATH中
# There are 3 ways to do this and either one can be used. type -p executable_name &>/dev/null hash executable_name &>/dev/null command -v executable_name &>/dev/null # As a test. if type -p executable_name &>/dev/null; then # Program is in PATH. fi # Inverse. if ! type -p executable_name &>/dev/null; then # Program is not in PATH. fi # Example (Exit early if program is not installed). if ! type -p convert &>/dev/null; then printf '%s\n' "error: convert is not installed, exiting..." exit 1 fi
使用获取当前日期 strftime
Bash printf有一个内置的获取日期的方法,可用于代替date命令。
CAVEAT:需要bash4+
示例功能:
date() {
# Usage: date "format" # See: 'man strftime' for format.
printf "%($1)T\\n" "-1" }
用法示例:
# Using above function. $ date "%a %d %b - %l:%M %p" Fri 15 Jun - 10:00 AM # Using printf directly. $ printf '%(%a %d %b - %l:%M %p)T\n' "-1" Fri 15 Jun - 10:00 AM # Assigning a variable using printf. $ printf -v date '%(%a %d %b - %l:%M %p)T\n' '-1' $ printf '%s\n' "$date" Fri 15 Jun - 10:00 AM
获取当前用户的用户名
CAVEAT:需要bash4.4+
$ : \\u # Expand the parameter as if it were a prompt string. $ printf '%s\n' "${_@P}" black
生成UUID V4
CAVEAT:生成的值不具有加密安全性。
示例功能:
uuid() { # Usage: uuid C="89ab" for ((N=0;N<16;++N)); do B="$((RANDOM%256))" case "$N" in 6) printf '4%x' "$((B%16))" ;;
8) printf '%c%x' "${C:$RANDOM%${#C}:1}" "$((B%16))" ;;
3|5|7|9) printf '%02x-' "$B" ;;
*) printf '%02x' "$B" ;; esac done printf '\n' }
用法示例:
$ uuid
d5b6c731-1310-4c24-9fe3-55d556d44374
进度条
这是一种绘制进度条的简单方法,无需
在函数本身中使用for循环。
示例功能:
bar() { # Usage: bar 1 10 # ^----- Elapsed Percentage (0-100). # ^-- Total length in chars. ((elapsed=$1*$2/100)) # Create the bar with spaces. printf -v prog "%${elapsed}s" printf -v total "%$(($2-elapsed))s" printf '%s\r' "[${prog// /-}${total}]" }
用法示例:
for ((i=0;i<=100;i++)); do # Pure bash micro sleeps (for the example). (:;:) && (:;:) && (:;:) && (:;:) && (:;:) # Print the bar. bar "$i" "10" done printf '\n'
获取脚本中的函数列表
get_functions() { # Usage: get_functions IFS=$'\n' read -d "" -ra functions < <(declare -F) printf '%s\n' "${functions[@]//declare -f }" }
绕过shell别名
# alias ls # command # shellcheck disable=SC1001 \ls
绕过shell函数
# function ls # command command ls
在后台运行命令
这将运行给定命令并使其保持运行,即使在终端或SSH连接终止后也是如此。忽略所有输出。
bkr() {
(nohup "$@" &>/dev/null &)
}
bkr ./some_script.sh # some_script.sh is now running in the background