nixhacks.net/content/posixish_functions.rst
2022-10-21 22:29:23 +03:00

190 lines
5.4 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

:title: Несколько полезных функций на Bourne Shell
:date: 18 Oct 22
==========================================
Несколько полезных функций на Bourne Shell
==========================================
Функции, описанные здесь можно применять в любой POSIX-совместимой оболочке.
Протестировано в **dash**. Примеры на этой странице будут обновляться.
**1. Парсер аргументов в стиле GNU**
.. code-block:: shell
optval() {
# GNU-style command line options parser
#
# Usage: optval "$1" "$2"
#
# Set variables:
# OPT - option name
# VAL - value
# SFT - value for shift command
OPT="${1%%=*}"; VAL="${1#*=}"; SFT=1
if [ "$OPT" = "$VAL" ]; then
if [ -n "$2" ] && [ "${2#"${2%%?}"}" != "-" ]; then
VAL="$2"; SFT=2
else
unset VAL
fi
fi
if [ -z "$VAL" ]; then
echo Missing argument for option "$OPT" >&2
exit 1
fi
}
Эта функция позволит надёжно распарсить опции с обязательным аргументом. Ей
по силам:
* **-o** *value*
* **--option**\ =\ *value*
* **--option**\ =\ *name=value*
* **-option** *value*
..и вариации.
Непосредственно в POSIX-оболочке работать с парсером будет тяжко из-за
отсутсвия массивов. Единственный доступный массив **$@** здесь занят. NULL в
качестве разделителя для списка позиционных аргументов использовать не
получится, поэтому ниже пример с двоеточием. В **Bash** таких проблем нет.
.. code-block:: shell
while [ "$#" -ne 0 ]; do
case "$1" in
-h|--help)
echo "Usage: $0 [-chv] [--] arguments"
exit 0
;;
-v|--version)
echo 1.0.0
exit 0
;;
-c|-c=*|--config|--config=*)
optval "$1" "$2"
config="$VAL"
shift "$SFT"
;;
--) # end of options processing
shift
break
;;
-*)
echo Unknown option "$1" >&2
exit 1
;;
*) # Save positional arguments
# In Bash better use ARGS+=("$1") instead
ARGS="$1":"$ARGS"
shift
esac
done
# Set positional arguments. It is not needed in Bash
# In Bash you can use ARGS array directly or use set -- "${ARGS[@]}"
OLDIFS="$IFS"; IFS=:
# $arg must be unquoted!
# shellcheck disable=SC2086
for arg in $ARGS; do set -- $arg "$@"; done
IFS="$OLDIFS"
echo Config: "$config"
echo Positional arguments:
for arg in "$@"; do; echo : "$arg"; done
**2. Интерактивный диалог**
.. code-block:: shell
confirm() {
# Confirmation interactive dialog
#
# Usage: confirm "message"
[ -n "$ASSUME_NO" ] && return 1
[ -n "$ASSUME_YES" ] && return 0
while true; do
printf '%s (y/n) ' "$*"
read -r REPLY
case "$REPLY" in
[Yy]|[Yy][Ee][Ss]) return 0;;
[Nn]|[Nn][Oo]) return 1;;
*) echo Please, answer y or n;;
esac
done
}
Здесь предусмотрены переменные ``ASSUME_NO`` и ``ASSUME_YES`` для
неинтерактивного режима. Автоматическое "Нет" и "Да" соответственно. Пример:
.. code-block:: shell
if confirm 'Proceed?'; then
echo OK
else
echo Abort
fi
**3. Версия Python**
Просто напечатает в STDOUT версию интерпретатора Python.
.. code-block:: shell
python_version() {
# Get Python interpreter version in format 'major.minor.micro' e.g. '3.10.2'
# Works with Python 2.x and 3.x.
#
# Usage: python_version [<path to interpreter>]
"${1:-python}" -c "import sys; v=sys.version_info; \
print('%s.%s.%s' % (v.major, v.minor, v.micro))"
}
**4. Открыть редактор по умолчанию**
.. code-block:: shell
default_editor() {
# Edit file in user's default editor
#
# Usage: default_editor file
if [ -n "$EDITOR" ]; then
"$EDITOR" "$@"
return 0
fi
if hash select-editor >/dev/null 2>&1; then
if [ -f ~/.selected_editor ]; then
. ~/.selected_editor
else
select-editor
. ~/.selected_editor
fi
"$SELECTED_EDITOR" "$@"
return 0
fi
if hash editor >/dev/null 2>&1; then
editor "$@"
return 0
else
vi "$@" # fallback to vi
return 0
fi
}
**5. Простой URL-decoder**
.. code-block:: shell
unescape_uri() {
echo "$1" | sed 's/%/\\\\x/g' | xargs printf
}