Какой последний аргумент предыдущей команды?

Я начал испытывать то же самое в Precise. Чтобы обойти эту проблему, я добавил файл /etc/apt/apt.conf.d/00bugs, который содержит одну строку:

APT :: Cache-start 200000000;

Ошибки сегментации больше не возникают. Я открыл для этого отчет об ошибке: https://bugs.launchpad.net/ubuntu/+source/apt/+bug/1445436

12
12.04.2018, 14:39
3 ответа

Чтобы ответить на вопрос заголовка, попробуйте!$:

$ export EDITOR="emacs -nw"
$ echo !$
EDITOR=emacs -nw

Это расширение истории. Из справочной страницы bash:

History expansion is performed immediately after a complete line is read, before the shell breaks it into words. It takes place in two parts. The first is to determine which line from the history list to use during substitution. The second is to select portions of that line for inclusion into the current one. The line selected from the history is the event, and the portions of that line that are acted upon are words.

...

Event Designators

...

! Start a history substitution, except when followed by a blank, newline, carriage return, = or ( (when the extglob shell option is enabled using the shopt builtin).

...

!! Refer to the previous command. This is a synonym for `!-1'.

...

Word Designators

...

$ The last word. This is usually the last argument, but will expand to the zeroth word if there is only one word in the line.

...

If a word designator is supplied without an event specification, the previous command is used as the event.

2
27.01.2020, 19:55

TL;DR :В случае export FOO=barbash вызывает создание временной среды, устанавливает FOO=barв этой среде, а затем выдает окончательную команду export FOO. В этот момент FOOпринимается в качестве последнего аргумента.


Ах, много -оскорбленных$_:

($_, an underscore.) At shell startup, set to the absolute pathname used to invoke the shell or shell script being executed as passed in the environment or argument list. Subsequently, expands to the last argument to the previous command, after expansion. Also set to the full pathname used to invoke each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file.

Рассмотрим несколько вариантов:

$ man; echo $_
What manual page do you want?
man
$ man foo; echo $_
No manual entry for foo
foo
$ echo; echo $_

echo
$ echo bar foo; echo $_
bar foo
foo
$ foo=x eval 'echo $foo'; echo $_
x
echo $foo
$ bar() { man $1; }; echo $_
foo
$ for (( i=0; $i<0; i=i+1 )); do echo $i; done; echo $_
foo
$ bar; echo $_
What manual page do you want?
man
$ bar foo; echo $_
No manual entry for foo
foo
$ MANPATH=/tmp; echo $_

$ export MANPATH=/tmp; echo $_
MANPATH

Итак, мы видим здесь три модели:

  • Команды, вызываемые из файловой системы, функций и встроенных -ins, ведут себя так, как обычно ожидается:$_устанавливается на имя самой команды, если нет аргументов, в противном случае последний из представленных аргументов.
  • После определения функций, циклов и других логических конструкций:$_не изменяется.
  • Все остальное:$_настроено на что-то не совсем ожидаемое; странный.

Я доработал код, чтобы пролить свет на странности.

$./bash --noprofile --norc -c 'man foo'
lastword=[man]
lastarg=[foo]
$./bash --noprofile --norc -c 'export FOO=bar'
lastword=[export]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[bar]
before bind_lastarg, lastarg=[FOO]
bind_lastarg, arg=[FOO]
bind_variable, name=[_], value=[FOO]
$./bash --noprofile --norc -c 'declare FOO=bar'
lastword=[declare]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[(null)]
before bind_lastarg, lastarg=[FOO=bar]
bind_lastarg, arg=[FOO=bar]
bind_variable, name=[_], value=[FOO=bar]

Вы можете видеть, что анализатор видит ожидаемый последний аргумент(lastarg=)во всех случаях, но то, что происходит после этого, зависит от того, что, по мнению bash, должно произойти. См. выполнить _cmd.c,выполнить _простую _команду ().

В случае export FOO=barbash выполняет присваивание, а затем экспортирует переменную. Кажется, это согласуется с утверждением документации о том, что последний аргумент вычисляется после раскрытия.

4
27.01.2020, 19:55

Bash обрабатывает присвоения переменных, когда они разрешены в качестве аргументов (с alias, declare, export, local, readonlyи typeset), прежде всего (или, скорее, он идентифицирует их прежде всего — расширение применяется к значениям, присвоенным переменным ). Когда дело доходит до расширения слов, остается команда export EDITOR, поэтому _устанавливается на EDITOR.

Вообще говоря, аргументы — это «слова», оставшиеся после раскрытия (, которые не включают присвоение переменных и перенаправление ).

Подробнее см. Расширение простой команды в руководстве Bash.

13
27.01.2020, 19:55

Теги

Похожие вопросы