Генерация команд с переменным расширением в цикле

Генерация команд с переменным расширением в цикле

Я хочу создать локальные псевдонимы, пока работаю в определенных каталогах. Например, я хотел бы иметь следующее в файле с именемlocal_alias

alias foo='bar'

Я хотел написать скрипт очистки, чтобы удалить эти псевдонимы после того, как я закончу работу. Что-то вроде:

egrep "alias [[:alnum:]]+" local_alias -o|while read i; do
  un$i
done

Если я изменю среднюю строку на echo un$i, вывод будет выглядеть как правильно отформатированная unaliasкоманда: unalias foo. Но в написанном виде я получаю unalias: foo: not found.

Если я попробую процитировать среднюю строку: "un$i", то вместо этого я получу unalias foo: command not found.

Что я делаю не так?

решение1

Псевдонимы специфичны для оболочки, поэтому, когда вы запускаете свой скрипт следующим образом:

#!/bin/bash

...
unalias ....
...

Он работает как дочерняя оболочка, которая обычно не имеет тех же псевдонимов. Усугубляя проблему, вы также имеете дело с другой проблемой. Как только скрипт завершается, дочерняя оболочка, чьи псевдонимы были удалены, исчезает, возвращая вас к родительской оболочке, которая все еще имеет свои псевдонимы нетронутыми.

Насколько мне известно, нет способа изменить псевдонимы вашей текущей оболочки таким образом.

Так как же это сделать?

Для выполнения этого действия можно создать псевдоним или функцию в рамках текущей оболочки.

Пример

решение псевдонима

$ alias unalias_local='egrep "alias [[:alnum:]]+" local_alias -o|while read i; do un$i; done'

функциональное решение

$ function unalias_local { egrep "alias [[:alnum:]]+" local_alias -o | \
    while read i; do un$i; done; }

Проблемы с вышеперечисленным

Автор OP предоставил эти решения для этого ответа, которые, как он заявил, будут работать в его сценарии. Но в общем случае вы не можете изменить псевдонимы в цепочке команд, переданных по конвейеру, как эта, потому что каждый конвейер вызывает подоболочку, которая не сможет коснуться оболочки родителя. Так что мы вернулись к той же проблеме, что и ранее со скриптом.

Чтобы обойти это ограничение, можно вместо этого указать список псевдонимов в качестве аргументов команды.

Пример

$ alias ali1="cmd1"
$ alias ali2="cmd2"

Подтвердите псевдонимы в нашей оболочке:

$ alias | grep -E "ali[12]"
alias ali1='cmd1'
alias ali2='cmd2'

Содержание local_alias:

$ cat local_alias 
alias ali1="cmd1"
alias ali2="cmd2"

Эта команда проанализирует имена псевдонимов из файла local_alias:

$ grep -oP "(?<=alias )([[:alnum:]]+)" local_alias
ali1
ali2

Мы можем использовать его для unaliasэтих псевдонимов следующим образом:

$ unalias $(grep -oP "(?<=alias )([[:alnum:]]+)" local_alias)
$

Теперь, когда мы убедились, что их больше нет:

$ alias | grep -E "ali[12]"
$

решение2

Похоже, вы запускаете этот код в отдельном скрипте. Это не сработает: вам нужно изменить конфигурацию запущенной оболочки, а сделать это из другого процесса вы не сможете. Этот код очистки должен быть в функции, определенной в вашем .bashrc.

Вторая проблема заключается в том, что конвейер также создает подпроцесс (подоболочку). Поэтому, если вы запустите этот код внутри интерактивной оболочки, команда unaliasудалит псевдоним — но только в подоболочке. Вам нужен другой подход, который не запускает команду unaliasв подоболочке.

Есть несколько решений, но самым простым будет создать список псевдонимов, а затем выполнить команду unaliasодин раз. Имена псевдонимов не могут содержать специальные символы, поэтому разбиение слов в списке псевдонимов будет вполне достаточно для генерации аргументов для unalias.

unalias $(egrep -o "alias [[:alnum:]]+" local_alias)

Связанный контент