Con base de datos (Base de datos GNU )4.2.2:
sed -r '
/^\s*$/ {
# blank line
:NEXT
N # append next line to pattern space - if none, autoprint PS and exit
s/^\s*$\n^\s*$//g;t NEXT # if 2 blank lines, clear PS and loop to NEXT
}
# else, autoprint PS and next/exit
' < $MYFILE
Это сочетание двух вещей. Во-первых, раскрытие фигурных скобок — это не шаблон, соответствующий именам файлов :, это чисто текстовая замена — см. В чем разница между `a[bc]d`(квадратными скобками )и `a {b,c}d`(фигурные скобки )? . Во-вторых, когда вы используете результат подстановки команд вне двойных кавычек (ls $(…)
), происходит только сопоставление с образцом (и разбиение слов :оператором «split+glob» ), а не полный повтор -. ] разбор.
С ls $(echo 'test?.txt')
команда echo 'test?.txt'
выводит строкуtest?.txt
(с последней новой строкой ). Подстановка команд приводит к строкеtest?.txt
(без последней новой строки, потому что подстановка команд удаляет завершающие символы новой строки ). Эта подстановка без кавычек подвергается разбиению на слова, в результате чего получается список, состоящий из одной строки test?.txt
, поскольку в ней нет пробельных символов (, точнее, нет символов из $IFS
). Затем каждый элемент этого одного списка элементов -подвергается условному раскрытию подстановочных знаков, и, поскольку в строке есть подстановочный знак ?
, расширение подстановочных знаков действительно происходит. Поскольку шаблон test?.txt
соответствует как минимум одному имени файла, элемент списка test?.txt
заменяется списком имен файлов, соответствующих шаблонам, в результате чего получается список из двух элементов -, содержащий test1.txt
и test2.txt
. Наконец, ls
вызывается с двумя аргументами test1
и test2
.
С помощью ls $(echo 'test{1,2}')
команда echo 'test{1,2}'
выводит строкуtest{1,2}
(с последней новой строкой ). Подстановка команды приводит к строке test{1,2}
. Эта замена без кавычек подвергается разбиению на слова, в результате чего получается список, состоящий из одной строки test{1,2}
. Затем каждый элемент этого одного списка элементов -подвергается условному расширению с подстановочными знаками,который ничего не делает (элемент остается как есть ), так как в строке нет подстановочного знака. Таким образом, ls
вызывается с одним аргументом test{1,2}
.
Для сравнения, вот что происходит с ls $(echo test{1,2})
. Команда echo test{1,2}
выводит строкуtest1 test2
(с последней новой строкой ). Подстановка команды приводит к строкеtest1 test2
(без последней новой строки ). Эта замена без кавычек подвергается разбиению на слова, в результате чего получаются две строки test1
и test2
. Затем, поскольку ни одна из строк не содержит подстановочного знака, они остаются в покое, поэтому ls
вызывается с двумя аргументами test1
и test2
.
Работает, если убрать кавычки
$ ls $(echo test{1,2})
test1 test2
The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and filename expansion.
Раскрытие скобок не происходит после подстановки команд. Вы можете использовать eval, чтобы вызвать еще один раунд расширения :
.eval echo $(echo '{1,2}lala')
Результат:
1lala 2lala
Эта проблема очень специфична для bash
, потому что они решили в bash
отделить раскрытие фигурных скобок от расширения имени файла (подстановки )и выполнить его первым, до всех остальных раскрытий.
Из справочной страницы bash
:
The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion.
В вашем примере bash
увидит ваши фигурные скобки только после того, как выполнит подстановку команды (на $(echo...)
), когда уже слишком поздно.
Это отличается от всех других оболочек, которые выполняют расширение фигурных скобок непосредственно перед (, а некоторые даже как часть )расширения имени пути (подстановки ). Это включает, но не ограничивается csh
, где впервые были изобретены скобки -.
$ csh -c 'ls `echo "test{1,2}.txt"`'
test1.txt test2.txt
$ ksh -c 'ls $(echo "test{1,2}.txt")'
test1.txt test2.txt
$ var=nope var1=one var2=two bash -c 'echo $var{1,2}'
one two
$ var=nope var1=one var2=two csh -c 'echo $var{1,2}'
nope1 nope2
Последний пример одинаков в csh
, zsh
, ksh93
, mksh
или fish
.
Кроме того, обратите внимание, что раскрытие фигурных скобок как часть подстановки также доступно через библиотечную функцию glob(3)
(, по крайней мере, в Linux и всех BSD ), а также в других независимых реализациях (напр. в Perl:perl -le 'print join " ", <test{1,2}.txt>'
).
Почему в bash
это было сделано по-другому, вероятно, за этим стоит история, но FWIW я не смог найти никакого логического объяснения, и я нахожу все постфактум -рационализации неубедительными.
Пожалуйста, попробуйте:::
ls $ (эхо-тест{1,2}\.txt)
С обратной косой чертой. Теперь это работает. Также удалите, как сказал предыдущий постер, кавычки. Точка предназначена не для сопоставления с образцом, а здесь ее следует воспринимать буквально как точку.