То, что вы спрашиваете, очень похоже на простую подоболочку .
Всякий раз, когда вы используете, инкапсулируйте свои команды в круглые скобки, например (ls)
, эта команда будет запущена в дочернем процессе текущей оболочки.
Для вашего примера:
(
alias test='ls'
alias new_command='ls'
test
new_command
)
Или, поскольку псевдонимы копируются в подоболочки
alias test='ls'
alias new_command='ls'
( test ) # one subshell
( new_command ) # another subshell
Если вам нужно, чтобы ваши команды выполнялись в той же подоболочке:
alias test='ls'
alias new_command='ls'
( test ; new_command ) # same subshell
Это зависит от того, как вы интерпретируете EAFP. В узком смысле это относится к использованию обработки исключений, для которой разработан Python, но это невозможно в некоторых языках, а в большинстве других и необычно, и настоятельно не рекомендуется. Однако в более широком смысле EAFP используется почти во всех языках программирования, особенно в сценариях оболочки.
Я предполагаю сценарии оболочки POSIX с небольшим акцентом на Bash . Примеры кода Python — Python 3.
Python — это язык программирования, наиболее тесно связанный с дихотомией Посмотрите, прежде чем прыгнуть (LBYL)против Легче попросить прощения, чем разрешения (EAFP). В Python EAFP обычно означает разрешение возбуждения и перехвата исключения, а не проверку успешности операции перед ее попыткой, что было бы способом LBYL.
Но это не единственные две возможности; иногда можно попытаться выполнить операцию, которая не вызовет исключения в случае сбоя, но проверить, не сбой ли он произошел после попытки, и действовать по-разному в зависимости от результата. В нем не используется обработка исключений, поэтому с точки зрения Python кажется странным называть его EAFP... но на самом деле он имеет гораздо больше общего с EAFP, чем с LBYL. Это своего рода "EAFP", который очень распространен в сценариях оболочки.
Я думаю, будет полезно начать с примеров Python не только потому, что эти термины тесно связаны с культурой Python, но и потому, что EAFP, LBYL и «EAFP» без исключений могут быть продемонстрированы простым и понятным образом в Питон. Предположим, d
имеет типdict
:
# EAFP
try:
print(d['foo'])
except KeyError:
print('Not found.')
# LBYL
if 'foo' in d:
print(d['foo'])
else:
print('Not found.')
# Exceptionless "EAFP"
v = d.get('foo')
if v is None:
print('Not found.')
else:
print(v)
Иногда мы используем простой LBYL в сценарии оболочки. Этот код, который поставляется в файле по умолчанию .bashrc
Debian и Ubuntu, проверяет, содержит ли домашний каталог обычный файл с именем .bash_aliases
. В противном случае не предпринимается никаких попыток его использования. Если это так, делается попытка получить его (для запуска каждой из его строк в качестве команды в текущей оболочке ). Хотя это зависит от состояния гонки , ошибки, которые могут возникнуть в этом случае, не наносят вреда, поэтому здесь это совершенно хороший выбор конструкции :
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
Предположим, однако, чточто вы хотели войти в подкаталог и выполнить операцию, которую вы не хотели бы случайно выполнять вне его. LBYL, по крайней мере, в чистом виде — плохой выбор. В этом примере операция представляет собой рекурсивное удаление, начиная с нескольких подкаталогов, соответствующих глобусу . (...Что несколько надумано, поскольку есть ряд других способов сделать это с разумной безопасностью. Если хотите, можете себе представить, что в этом каталоге есть еще что делать до и/или после запуска rm
.)
# Don't do it this way!
if [ -d drafts ] && [ -x drafts ]; then # BAD!
cd drafts # BAD!
rm -r foo* # BAD!
fi # BAD!
Здесь я попытался проверить, удастся ли изменить каталог на drafts
. Я проверил, существует ли он и является ли он каталогом(-d
)и есть ли у меня права на его выполнение (-x
). Для каталога в системе *nix разрешения на выполнение позволяют мне перейти в него. (Обычно.)
Проблема, помимо значительной сложности этого подхода, заключается в том, что я мог что-то упустить. Даже если ничего не изменится, действительно ли это гарантирует , что я смогу зайти в каталог? Я все проверил? [Я оставляю это упражнение читателю.]
Кроме того, даже если бы я все проверил и убедился, что каталог существует и доступен, ну... был. В этом случае состояние гонки действительно имеет значение. Если что-то изменится, и я не смогу зайти в каталог, а команда cd
не сработает, то я удалю все драгоценные подкаталоги foo*
, существующие рядом с drafts
, вместо мусорных, содержащихся в нем. !
Вы можете заметить поразительное сходство между этими соображениями и некоторыми причинами использования EAFP в Python:избежанием сложного или трудного для чтения кода и риском того, что условия могли измениться между проверкой и попыткой операции на основе проверки . Действительно, это намного проще и надежнее, чем показанный выше плохой способ :
.if cd drafts; then
rm -r foo*
fi
Вместо этого вы можете увидеть, что это написано таким образом, особенно если желательно, чтобы все это имело статус выхода с ошибкой, если условие(cd drafts
)не выполняется:
cd drafts && rm -r foo*
Это не использует ничего похожего на обработку исключений. Но он не смотрит, прежде чем он прыгает. Он не проверяет наличие и доступность каталога drafts
. Он просто пытается измениться в него. Затем после выполнения попытки он проверяет, удалось ли это, и отказывается от продолжения выполнения команды rm
, если это не так.
Если под EAFP вы подразумеваете использование обработки исключений, то это не EAFP. Я понимаю, если вы отказываетесь от сравнения; в конце концов, этот подход существовал задолго до обработки исключений и распространен в таких языках, как C. Но он преследует некоторые из тех же целей и подходит во многих подобных ситуациях.
Конечно, на самом деле это более типичная форма прощения вместо разрешения в программировании. Python редок тем, что его не обескураживают --, а даже поощряют --генерировать исключения даже в совершенно обычных ситуациях.
Я частично согласен с ответом jas -. Хотя на самом деле они не являются основным способом обработки ошибок (в смысле сбоя команды ), ловушки в сценариях оболочки в некоторой степени сопоставимы с обработкой исключений в Python.
Тем не менее,есть пара важных практических различий между ловушками в сценариях оболочки и исключениями в Python:
Ловушки редко используются для управления потоком в сценариях оболочки и не так часто используются для обработки ошибок, в случаях, когда есть другие варианты. Чтобы запустить команду и узнать, сработала ли она, вы проверяете ее статус выхода . Как показано выше, управляющие структуры, такие как if
, предоставляют способ сделать это (и , есть и другие).