zoukankan      html  css  js  c++  java
  • 全宇宙最全的bash 脚本常见用法总结!


    shopt -s extdebug f()(printf '%s ' "${BASH_ARGV[@]}"); f "$@" shopt -u extdebug }

    用法示例:

    $ reverse_array 1 2 3 4 5
    5
    4
    3
    2
    1
    
    $ arr=(red blue green)
    $ reverse_array "${arr[@]}"
    green
    blue
    red
    
    

    删除重复的数组元素

    创建临时关联数组。设置关联数组
    值并发生重复赋值时,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
    ' "${!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
    ' "${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
    ' "$i"
    done
    
    

    循环遍历可变数字范围

    替代seq

    # Loop from 0-VAR.
    VAR=50
    for ((i=0;i<=VAR;i++)); do
        printf '%s
    ' "$i"
    done
    
    

    循环数组

    arr=(apples oranges tomatoes)
    
    # Just elements.
    for element in "${arr[@]}"; do
        printf '%s
    ' "$element"
    done
    
    

    循环遍历带索引的数组

    arr=(apples oranges tomatoes)
    
    # Elements and index.
    for i in "${!arr[@]}"; do
        printf '%s
    ' "${arr[i]}"
    done
    
    # Alternative method.
    for ((i=0;i<${#arr[@]};i++)); do
        printf '%s
    ' "${arr[i]}"
    done
    
    

    循环遍历文件的内容

    while read -r line; do
        printf '%s
    ' "$line"
    done < "file"
    
    

    循环遍历文件和目录

    不要用ls

    # Greedy example.
    for file in *; do
        printf '%s
    ' "$file"
    done
    
    # PNG files in dir.
    for file in ~/Pictures/*.png; do
        printf '%s
    ' "$file"
    done
    
    # Iterate over directories.
    for dir in ~/Downloads/*/; do
        printf '%s
    ' "$dir"
    done
    
    # Brace Expansion.
    for file in /path/to/parentdir/{file1,file2,subdir/file3}; do
        printf '%s
    ' "$file"
    done
    
    # Iterate recursively.
    shopt -s globstar
    for file in ~/Pictures/**/*; do
        printf '%s
    ' "$file"
    done
    shopt -u globstar
    
    

    文件处理

    CAVEAT: bash在版本中不能正确处理二进制数据< 4.4

    将文件读取为字符串

    替代cat命令。

    file_data="$(<"file")"
    
    

    将文件读取到数组(按行

    替代cat命令。

    # Bash <4
    IFS=$'
    ' 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
    ' "${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
    ' "${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
    ' "${#lines[@]}"
    }
    
    

    示例函数(bash 3):

    此方法使用的内存少于mapfile方法,并在bash3中工作,但对于较大的文件,它的速度较慢。

    lines_loop() {
        # Usage: lines_loop "file"
        count=0
        while IFS= read -r _; do
            ((count++))
        done < "$1"
        printf '%s
    ' "$count"
    }
    
    

    用法示例:

    $ lines ~/.bashrc
    48
    
    $ lines_loop ~/.bashrc
    48
    
    

    计算目录中的文件或目录

    这是通过将glob的输出传递给函数然后计算参数的数量来实现的。

    示例功能:

    count() {
        # Usage: count /path/to/dir/*
        #        count /path/to/dir/*/
        printf '%s
    ' "$#"
    }
    
    

    用法示例:

    # 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=$'
    ' read -r line; do
            [[ $extract && $line != "$3" ]] &&
                printf '%s
    ' "$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
    ' "${1%/*}/"
    }
    
    

    用法示例:

    $ dirname ~/Pictures/Wallpapers/1.jpg
    /home/black/Pictures/Wallpapers/
    
    $ dirname ~/Pictures/Downloads/
    /home/black/Pictures/
    
    

    获取文件路径的基本名称

    替代basename命令。

    示例功能:

    basename() {
        # Usage: basename "path"
        : "${1%/}"
        printf '%s
    ' "${_##*/}"
    }
    
    

    用法示例:

    $ 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
    ' "${!ref}"
    value
    
    

    或者,在bash4.3+上:

    $ hello_world="value"
    $ var="world"
    
    # Declare a nameref.
    $ declare -n ref=hello_$var
    
    $ printf '%s
    ' "$ref"
    value
    
    

    根据另一个变量命名变量

    $ var="world"
    $ declare "hello_$var=value"
    $ printf '%s
    ' "$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颜色。 RGB
    e[48;2;<R>;<G>;<B>m 将文本背景颜色设置为RGB颜色。 RGB

    文字属性

    序列它有什么作用?
    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[2Je[H 清除屏幕并将光标移动到0,0

    参数扩展

    间接

    参数它有什么作用?
    ${!VAR} 根据值访问变量VAR
    ${!VAR*} 展开为IFSVAR。开头的变量名称的分隔列表。
    ${!VAR@} 展开为IFSVAR。开头的变量名称的分隔列表。如果是双引号,则每个变量名称都会扩展为单独的单词。

    替换

    参数它有什么作用?
    ${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为空或未设置,请将值设置VARSTRING
    ${VAR=STRING} 如果VAR未设置,请将值设置VARSTRING
    ${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 如果filefile2使用修改时间)更新或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使用时,之间的不同整数032767被返回。此变量不应用于与安全性相关的任何内容(包括加密密钥等)。

    "$RANDOM"
    
    

    有关终端的信息

    获取行和列中的终端大小(来自脚本

    在纯bash中编写脚本和sttytput无法
    调用时,这很方便。

    示例功能:

    get_term_size() {
        # Usage: get_term_size
    
        # (:;:) is a micro sleep to ensure the variables are
        # exported immediately.
        shopt -s checkwinsize; (:;:)
        printf '%s
    ' "$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
    ' "${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
    ' "$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
    ' "$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
    ' "$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
    ' "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
    ' "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
    ' "-1"
    Fri 15 Jun  - 10:00 AM
    
    # Assigning a variable using printf.
    $ printf -v date '%(%a %d %b  - %l:%M %p)T
    ' '-1'
    $ printf '%s
    ' "$date"
    Fri 15 Jun  - 10:00 AM
    
    

    获取当前用户的用户名

    CAVEAT:需要bash4.4+

    $ : \u
    # Expand the parameter as if it were a prompt string.
    $ printf '%s
    ' "${_@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 '
    '
    }
    
    

    用法示例:

    $ 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
    ' "[${prog// /-}${total}]"
    }
    
    

    用法示例:

    for ((i=0;i<=100;i++)); do
        # Pure bash micro sleeps (for the example).
        (:;:) && (:;:) && (:;:) && (:;:) && (:;:)
    
        # Print the bar.
        bar "$i" "10"
    done
    
    printf '
    '
    
    

    获取脚本中的函数列表

    get_functions() {
        # Usage: get_functions
        IFS=$'
    ' read -d "" -ra functions < <(declare -F)
        printf '%s
    ' "${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
    
    

    参考

    https://en.wikibooks.org/wiki/Bash_Shell_Scripting

    后记

    谢谢阅读

  • 相关阅读:
    多线程之生产者和消费者模式
    python多线程之线程同步--锁
    python多线程之动态确定线程数
    python多线程之循环,调用函数等
    V8 引擎是如何工作的?
    AST抽象语法树——最基础的javascript重点知识,99%的人根本不了解
    字节码
    V8 引擎是如何工作的?
    JavaScript arguments对象
    V8 是怎么跑起来的 —— V8 中的对象表示
  • 原文地址:https://www.cnblogs.com/lucius/p/10965638.html
Copyright © 2011-2022 走看看