Bash/函數

出自 Arch Linux 中文维基

Bash 也支持函數。將函數添加到 ~/.bashrc,或從 ~/.bashrc source 的單獨文件。更多 Bash 函數示例可以在 BBS#30155 中找到。

顯示錯誤代碼[編輯 | 編輯原始碼]

要設置 trap 以攔截上次運行的程序的非零返回代碼,請執行以下操作:

EC() {
	echo -e '\e[1;33m'code $?'\e[m\n'
}
trap EC ERR

動態編譯和執行 C 源代碼[編輯 | 編輯原始碼]

下面的函數將編譯(在 /tmp/ 目錄中)並動態執行 C 源參數(並且執行過程將不帶參數)。最後,在程序終止後,將刪除已編譯的文件。

# 动态编译和执行 C 源代码
csource() {
	[[ $1 ]]    || { echo "缺少操作数" >&2; return 1; }
	[[ -r $1 ]] || { printf "文件 %s 不存在或不可读\n" "$1" >&2; return 1; }
	local output_path=${TMPDIR:-/tmp}/${1##*/};
	gcc "$1" -o "$output_path" && "$output_path";
	rm "$output_path";
	return 0;
}

提取[編輯 | 編輯原始碼]

下面的函數將提取各種壓縮文件類型。將其與語法 extract <file1> <file2> ... 一起使用

extract() {
    local c e i

    (($#)) || return

    for i; do
        c=''
        e=1

        if [[ ! -r $i ]]; then
            echo "$0: 文件不可读: \`$i'" >&2
            continue
        fi

        case $i in
            *.t@(gz|lz|xz|b@(2|z?(2))|a@(z|r?(.@(Z|bz?(2)|gz|lzma|xz|zst)))))
                   c=(bsdtar xvf);;
            *.7z)  c=(7z x);;
            *.Z)   c=(uncompress);;
            *.bz2) c=(bunzip2);;
            *.exe) c=(cabextract);;
            *.gz)  c=(gunzip);;
            *.rar) c=(unrar x);;
            *.xz)  c=(unxz);;
            *.zip) c=(unzip);;
            *.zst) c=(unzstd);;
            *)     echo "$0: 无法识别的文件扩展名: \`$i'" >&2
                   continue;;
        esac

        command "${c[@]}" "$i"
        ((e = e || $?))
    done
    return "$e"
}
注意: 確保 extglob 已啟用:shopt -s extglob,方法是將其添加到 ~/.bashrc 中(參見 gregswiki:glob#Options which change globbing behavior)。

另一種方法是安裝專門的軟件包,請參閱歸檔與壓縮#便利工具

cd 與 ls 合二為一[編輯 | 編輯原始碼]

通常更改到一個目錄之後會使用 ls 命令來列出它的內容。因此,讓第二個函數同時執行這兩個操作是很有幫助的。

在這個例子中,我們將它命名為 cl(change list),如果指定的目錄不存在,則顯示一條錯誤消息。

cl() {
	local dir="$1"
	local dir="${dir:=$HOME}"
	if [[ -d "$dir" ]]; then
		cd "$dir" >/dev/null; ls
	else
		echo "bash: cl: $dir: 找不到目录"
	fi
}

當然,可以修改 ls 命令以滿足您的需要,例如 ls -hall --color=auto

簡單的記錄者[編輯 | 編輯原始碼]

note () {
    # 若文件不存在,则创建它
    if [[ ! -f $HOME/.notes ]]; then
        touch "$HOME/.notes"
    fi

    if ! (($#)); then
        # 无参数,印出文件
        cat "$HOME/.notes"
    elif [[ "$1" == "-c" ]]; then
        # 清除文件
        printf "%s" > "$HOME/.notes"
    else
        # 添加所有参数到文件
        printf "%s\n" "$*" >> "$HOME/.notes"
    fi
}

簡單的任務實用程序[編輯 | 編輯原始碼]

靈感來自#簡單的記錄者

todo() {
    if [[ ! -f $HOME/.todo ]]; then
        touch "$HOME/.todo"
    fi

    if ! (($#)); then
        cat "$HOME/.todo"
    elif [[ "$1" == "-l" ]]; then
        nl -b a "$HOME/.todo"
    elif [[ "$1" == "-c" ]]; then
        > $HOME/.todo
    elif [[ "$1" == "-r" ]]; then
        nl -b a "$HOME/.todo"
        eval printf %.0s- '{1..'"${COLUMNS:-$(tput cols)}"\}; echo
        read -p "键入要删除的数字: " number
        sed -i ${number}d $HOME/.todo "$HOME/.todo"
    else
        printf "%s\n" "$*" >> "$HOME/.todo"
    fi
}

計算器[編輯 | 編輯原始碼]

calc() {
    echo "scale=3;$@" | bc -l
}

Kingbash[編輯 | 編輯原始碼]

Kingbash - 菜單驅動的自動完成(參見 BBS#101010)。

AUR 安裝 kingbash-gb-gitAUR,然後將以下內容插入你的 ~/.bashrc

function kingbash.fn() {
    echo -n "KingBash> $READLINE_LINE" #其中 "KingBash> " 看起来最像你的 PS1,至少在长度上是这样的。
    OUTPUT=$(/usr/bin/kingbash "$(compgen -ab -A function)")
    READLINE_POINT=$(echo "$OUTPUT" | tail -n 1)
    READLINE_LINE=$(echo "$OUTPUT" | head -n -1)
    echo -ne "\r\e[2K"
}
bind -x '"\t":kingbash.fn'

IP 信息[編輯 | 編輯原始碼]

有關 bash 中的 IP 地址或主機名的詳細信息,通過 https://ipinfo.io 查詢:

ipif() { 
    if grep -P "(([1-9]\d{0,2})\.){3}(?2)" <<< "$1"; then
	 curl ipinfo.io/"$1"
    else
	ipawk=($(host "$1" | awk '/address/ { print $NF }'))
	curl ipinfo.io/${ipawk[1]}
    fi
    echo
}
注意: Bash 僅限於擴展正則表達式;此示例在 grep 中使用 perl 正則表達式。[1]