Bash (Русский)/Functions (Русский)

From ArchWiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Состояние перевода: На этой странице представлен перевод статьи Bash/Functions. Дата последней синхронизации: 10 июля 2021. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.

Bash также поддерживает функции. Функции можно добавлять напрямую в ~/.bashrc или же в отдельный файл, который затем будет считан и исполнен из ~/.bashrc. Дополнительные примеры можно найти на форуме.

Отображение кодов ошибок

Создайте trap для перехвата ненулевого (означающего ошибку) кода возврата из последней запущенной программы:

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

Компиляция и запуск кода Cи на лету

Представленная ниже функция скомпилирует (в каталоге /tmp/) и запустит файл с исходным кодом на языке Си "на лету" (запуск будет произведен без аргументов). После завершения работы программы скомпилированный файл будет удален.

csource() {
	[[ $1 ]]    || { echo "Missing operand" >&2; return 1; }
	[[ -r $1 ]] || { printf "File %s does not exist or is not readable\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: file is unreadable: \`$i'" >&2
            continue
        fi

        case $i in
            *.t@(gz|lz|xz|b@(2|z?(2))|a@(z|r?(.@(Z|bz?(2)|gz|lzma|xz)))))
                   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: unrecognized file extension: \`$i'" >&2
                   continue;;
        esac

        command "${c[@]}" "$i"
        ((e = e || $?))
    done
    return "$e"
}
Примечание: Убедитесь, что опция extglob включена: shopt -s extglob. Для удобства можно добавить эту команду в ~/.bashrc. Подробнее см. gregswiki:glob#Options which change globbing behavior.

То же самое можно сделать с помощью специальных пакетов, см. Archiving and compression tools#Convenience tools.

cd и ls одной командой

Очень часто после смены каталога пользователь запускает ls, чтобы просмотреть его содержимое. Есть определённый смысл объединить cd и 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: Directory not found"
	fi
}

Команду ls можно модифицировать, например ls -hall --color=auto.

Простая записная книжка

note () {
    # if file doesn't exist, create it
    if [[ ! -f $HOME/.notes ]]; then
        touch "$HOME/.notes"
    fi

    if ! (($#)); then
        # no arguments, print file
        cat "$HOME/.notes"
    elif [[ "$1" == "-c" ]]; then
        # clear file
        printf "%s" > "$HOME/.notes"
    else
        # add all arguments to file
        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 "Type a number to remove: " 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).

Установите пакет kingbash-gb-gitAUR из AUR, после чего добавьте следующий код в ~/.bashrc:

function kingbash.fn() {
    echo -n "KingBash> $READLINE_LINE" #Where "KingBash> " looks best if it resembles your PS1, at least in length.
    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-адресе

Подробная информация об 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 доступны только регулярные выражения типа extended. В примере утилита grep использует регулярные выражения языка Perl [1].