Почему делает восклицательный знак'!' иногда удар нарушения?

Следующее решение считает фактическое количество используемого inodes, начинающего с текущего каталога:

find . -print0 | xargs -0 -n 1 ls -id | cut -d' ' -f1 | sort -u | wc -l

Для получения количества файлов того же подмножества используйте:

find . | wc -l

Для решений, исследуя только подкаталоги, не принимая во внимание файлы в текущем каталоге, можно обратиться к другим ответам.

13
24.08.2011, 01:44
3 ответа

! символ вызывает замену истории удара. При сопровождении строкой (как в провальном примере), он пытается расшириться до последнего события истории, которое началось с той строки. Точно так же, как $var расширен до значения той строки, !echo расширился бы до последней команды эха в Вашей истории.

Пространство является повреждающимся символом в таких расширениях. Сначала отметьте, как это работало бы с переменными:

# var="like"
# echo "$var"
like
# echo "$"
$
# echo "Do you $var frogs?"
Do you like frogs?       <- as expected, variable name broken at space
# echo "Do you $varfrogs?"
Do you?                  <- $varfrogs not defined, replaced with blank
# echo "Do you $ var frogs?"
Do you $ var frogs?      <- $ not a valid variable name, ignored

То же самое произойдет для расширения истории. Символ удара (!) начинается заменяющая последовательность истории, но только если сопровождаемый строкой. Следующий за этим с пространством делают это литеральным ударом вместо части последовательности замены.

Можно избежать этого вида замены и для переменной и для истории expantion при помощи одинарных кавычек. Ваши первые примеры использовали одинарные кавычки и так хорошо работали. Ваши последние примеры находятся в двойных кавычках и таким образом колотят, просканировал их для последовательностей expantion, прежде чем это сделало что-либо еще. Единственная причина первый не смещался, состоит в том, что это пространство является символом прерывания как показано выше.

11
27.01.2020, 19:53
  • 1
    Спасибо Caleb.. Другое из моих предвзятых мнений отклонено... Я думал, что парсинг удара был сделан от самой внутренней скобки или фигурной скобки, и затем работал за пределы... Кажется, что удар анализирует по-другому к моему предположению. –  Peter.O 23.08.2011, 16:01
  • 2
    путает достаточно в ударе без него изменяющийся во вложенных строках. Как это, замены происходят очень вначале в процессе. Рассмотрите этот пример: var=word; echo "test '$var'"; echo 'test "$var"' –  Caleb 23.08.2011, 16:12
  • 3
    .. Да undestood. Я знал о вложенных кавычках в кавычках... Мое недоразумение состояло в том, что я думал, что код в скобках замены команды будет проанализирован отдельно, к тому, что окружает те скобки; но по-видимому нет..спасибо. –  Peter.O 23.08.2011, 16:30

Как уже сказано Caleb, ! используется для вызова замены истории удара.

Если как я Вы чувствуете, что Вам не нужна такая функция, можно отключить ее вставляющий следующую строку в ~/.bashrc:

set +H

Мне не нужен он, потому что история может быть восстановлена стрелкой вверх и Ctrl-r возрастающий обратный поиск. См. страницу руководства удара, раздел Commands for Manipulating the History для подробного списка ярлыков.

6
27.01.2020, 19:53
  • 1
    Как Вы живете без !!? –  Caleb 23.08.2011, 15:54
  • 2
    Спасибо., я думал бы, что это могло быть проблемой, мудрой мобильностью, но использование set +H в сценарии работает точно также :) +1 –  Peter.O 23.08.2011, 15:57
  • 3
    @fred: странный, обычно расширение истории находится "на" только для интерактивных оболочек. –  enzotib 23.08.2011, 16:03
  • 4
    @enzo.. Еще раз спасибо.. Я протестировал его от командной строки.. А-ч! Если бы изучение не было такой забавой, то это было бы утомительно..., я упоминал кофе? помогает также, что Заключение в кавычки :) –  Peter.O 23.08.2011, 16:08
  • 5
    Ya, это - глюк. У меня есть вставляемый код копии из сценариев, которые перестали работать на командной строке по просто этой причине. Расширение истории не было беспокойством в сценарии, но это находится на интерактивной оболочке. –  Caleb 23.08.2011, 16:16

ваш первый пример:

{ echo -e "foo\nbar" | sed -nre '/foo/! p'
    echo -e "foo\nbar" | sed -nre '/foo/!p'; }

может быть сокращено до

echo '! p' 
echo '!p'

В одинарных кавычках все символы сохраняют свои буквальные значения. Итак ! потерял свое особое значение, и расширение истории не выполнено.

ваш второй и третий примеры:

var="$(echo -e "foo\nbar" | sed -nre '/foo/! p')"; echo "$var"

var="$(echo -e "foo\nbar" | sed -nre '/foo/!p')"; echo "$var"

может быть сокращено до

echo "'! p'"

echo "'!p'"

'! p ' и '! p ' по сути являются частями строк в двойных кавычках.

В двойных кавычках все символы сохраняют свои буквальные значения , кроме $ , `, \ и ! .

Это подразумевает одинарные кавычки '! p ' и '! p ' утратили свое особое значение (т.е. невозможно сбежать ! ), но ! по-прежнему сохраняет свое особое значение, поэтому выполняется расширение истории.

Однако, когда ! За следует пробел, раскрытие истории не выполняется.

Цитата из man bash :

ЦИТАТА

[...]

Заключение символов в одинарные кавычки сохраняет буквальное значение каждого символа в кавычках. [...]

Заключение символов в двойные кавычки сохраняет буквальное значение всех символов в кавычках, за исключением $, `, \, и, когда раскрытие истории включено, !. [...] Если этот параметр включен, раскрытие истории будет выполняться, если! заключенные в двойные кавычки экранируются обратной косой чертой. Обратная косая черта перед! не удаляется.

РАСШИРЕНИЕ ИСТОРИИ

[...]

Расширение истории начинается с появления символа расширения истории , который есть! по умолчанию. Только обратная косая черта (\) и одинарные кавычки могут заключать в кавычки символ раскрытия истории.

Некоторые символы запрещают раскрытие истории, если они встречаются сразу после символа раскрытия истории, даже если он не заключен в кавычки: пробел, табуляция, новая строка, возврат каретки и =. Если включена опция оболочки extglob , (также будет запрещать расширение.

2
27.01.2020, 19:53

Теги

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