Получите развертывание псевдонима (в bash и zsh)

Вопрос или проблема

Я хочу получить раскрытие псевдонима.

Например, если у меня есть:

alias g=hub
alias cdh="cd $HOME"

Я хочу, чтобы было:

expand_alias g == hub

expand_alias cdh == cd $HOME

Интересно, что в двух оболочках вывод различается:

bash:

$ alias g cdh
alias g='git'
alias cdh="cd $HOME"

zsh:

% alias g cdh
g=hub
cdh="cd $HOME"

Обратите внимание, что нет префикса alias и нет кавычек вокруг hub.

В zsh вы можете просто использовать

get_alias() {
  printf '%s\n' $aliases[$1]
}

С bash (при условии, что он не находится в режиме POSIX, в этом случае его alias даст вывод, аналогичный zsh), вы можете сделать:

get_alias() (
  eval '
    alias() { printf "%s\n" "${1#*=}"; }'"
    $(alias -- "$1")"
)

В основном, мы оцениваем вывод alias после того, как переопределяем alias как функцию, которая выводит то, что находится справа от первого = в ее первом аргументе.

Вы можете использовать схожий подход для чего-то, совместимого с большинством оболочек POSIX, zsh и bash:

get_alias() {
  eval "set -- $(alias -- "$1")"
  [ "$#" -gt 0 ] || return
  eval 'printf "%s\n" "${'"$#"'#*=}"'
}

Исходя из ответа Стефана Шазеля, я придумал:

function alias_expand {
  if [[ $ZSH_VERSION ]]; then
    # shellcheck disable=2154  # псевдонимы ССылки, но не присвоены
    [ ${aliases[$1]+x} ] && printf '%s\n' "${aliases[$1]}" && return
  else  # bash
    [ "${BASH_ALIASES[$1]+x}" ] && printf '%s\n' "${BASH_ALIASES[$1]}" && return
  fi
  false  # Ошибка: псевдоним не определен
}

(с bash 4.0 или новее).

А как насчет определения функции оболочки:

EXA() { alias $@ | sed 's/^/expand_/; s/=/ == /; s/\o047//g; '; }

В моей zsh это было связано с комбинацией клавиш:

_expand_alias () {
    local word expl tmp pre sel what
    local -a tmpa suf
    eval "$_comp_setup"
    if [[ -n $funcstack[2] ]]
    then
        if [[ "$funcstack[2]" = _prefix ]]
        then
            word="$IPREFIX$PREFIX$SUFFIX"
        else
            word="$IPREFIX$PREFIX$SUFFIX$ISUFFIX"
        fi
        pre=()
    else
        local curcontext="$curcontext"
        if [[ -z "$curcontext" ]]
        then
            curcontext="expand-alias-word:::"
        else
            curcontext="expand-alias-word:${curcontext#*:}"
        fi
        word="$IPREFIX$PREFIX$SUFFIX$ISUFFIX"
        pre=(_main_complete - aliases)
    fi
    zstyle -s ":completion:${curcontext}:" regular tmp || tmp=yes
    case $tmp in
        (always) sel=r  ;;
        (yes | 1 | true | on) [[ CURRENT -eq 1 ]] && sel=r  ;;
    esac
    zstyle -T ":completion:${curcontext}:" global && sel="g$sel"
    zstyle -t ":completion:${curcontext}:" disabled && sel="${sel}${(U)sel}"
    tmp=
    [[ $sel = *r* ]] && tmp=$aliases[$word]
    [[ -z $tmp && $sel = *g* ]] && tmp=$galiases[$word]
    [[ -z $tmp && $sel = *R* ]] && tmp=$dis_aliases[$word]
    [[ -z $tmp && $sel = *G* ]] && tmp=$dis_galiases[$word]
    if [[ -n $tmp ]]
    then
        tmp=${tmp%%[[:blank:]]##}
        if [[ $tmp[1] = [[:alnum:]_] ]]
        then
            tmpa=(${(z)tmp})
            if [[ $tmpa[1] = $word && $tmp = $aliases[$word] ]]
            then
                tmp="\\$tmp"
            fi
        fi
        zstyle -T ":completion:${curcontext}:" add-space || suf=(-S '')
        $pre _wanted aliases expl alias compadd -UQ "$suf[@]" -- ${tmp%%[[:blank:]]##}
    elif (( $#pre )) && zstyle -t ":completion:${curcontext}:" complete
    then
        $pre _aliases -s "$sel" -S ''
    else
        return 1
    fi
}

В моей среде zsh, когда я печатаю alias без команды, я получаю на stdout список всех псевдонимов. То же самое происходит в bash (на MacOS оба). Они представлены в форме alias=expansion

Итак, вы можете отфильтровать ещё больше с помощью sed: alias | sed -ne 's/cdh=\(.*\)$/\1/p', если “cdh” это псевдоним, который вы хотите узнать. Вы можете создать функцию оболочки в вашем профиле для этого, если это обычная задача для вас: например,

expand_alias() { alias $@ | sed -ne 's/^'$@'=\(.*\)$/\1/p' }

Если псевдоним заканчивается пробелом, следующий псевдоним также будет раскрыт, таким образом очень простая альтернатива:

$ alias expand_alias="echo "
$ expand_alias expand_alias
echo

Тестировано на GNU bash 5.1.16 и zsh 5.5.1.

Из справочного руководства по Bash:

Если последний символ значения псевдонима является пробелом, следующая команда, следующая за псевдонимом, также проверяется на раскрытие псевдонима.

Ответ или решение

Чтобы получить расширение псевдонима (алиаса) в оболочках Bash и Zsh, можно воспользоваться различными подходами, так как оба интерпретатора имеют свои особенности.

В Bash:

Вы можете определить функцию, которая будет извлекать значение алиаса, используя массивы встроенных переменных BASH_ALIASES. Например:

function get_alias() {
  # Проверяем, есть ли алиас
  if [ "${BASH_ALIASES[$1]+x}" ]; then
    printf '%s\n' "${BASH_ALIASES[$1]}"
    return
  fi
  false  # Алиас не определен
}

Использование этой функции будет следующим:

$ alias g=hub
$ get_alias g
hub

Этот способ работает для версий Bash 4.0 и новее. Если вы находитесь в строгом режиме POSIX, попробуйте переопределить команду alias:

get_alias() (
  eval '
    alias() { printf "%s\n" "${1#*=}"; }'
    $(alias -- "$1")
)

В Zsh:

В Zsh это делается проще благодаря тому, что исследовать алиасы можно через ассоциативные массивы:

function get_alias() {
  # Проверяем, есть ли алиас
  if [ ${aliases[$1]+x} ]; then
    printf '%s\n' "${aliases[$1]}"
    return
  fi
  false  # Алиас не определен
}

Применение этой функции:

% alias g=hub
% get_alias g
hub

Общий подход для обеих оболочек:

Если вы хотите создать функцию, которая будет работать как для Bash, так и для Zsh, можно объединить оба подхода. Вот пример такой функции:

function expand_alias() {
  if [[ $ZSH_VERSION ]]; then
    # Обрабатываем Zsh
    [ ${aliases[$1]+x} ] && printf '%s\n' "${aliases[$1]}" && return
  else
    # Обрабатываем Bash
    [ "${BASH_ALIASES[$1]+x}" ] && printf '%s\n' "${BASH_ALIASES[$1]}" && return
  fi
  false  # Алиас не определен
}

Теперь вы можете вызывать expand_alias с именем псевдонима для получения его значения.

Заключение

Эти методы позволяют получить расширение алиасов как в Bash, так и в Zsh. Выбор способа зависит от ваших предпочтений и среды, в которой вы работаете. Оба подхода достаточно просты в реализации и использовании, что делает их полезным дополнением к любой оболочке для работы с командной строкой.

Оцените материал
Добавить комментарий

Капча загружается...