Выражение с подстановочными знаками ZSH, ограничивающее поддержку повторения?

Вы можете поменять потоки местами. Это позволит вам grep оригинальный поток стандартной ошибки, получая при этом вывод, который изначально шел на стандартный вывод в терминале:

somecommand 3>&2 2>&1 1>&3- | grep 'pattern'

Это работает путем создания нового файлового дескриптора (3), открытого для вывода, и установки его на поток стандартной ошибки (3>&2). Затем мы перенаправляем стандартную ошибку на стандартный вывод (2>&1). Наконец, стандартный вывод перенаправляется на исходную стандартную ошибку, а новый дескриптор файла закрывается (1>&3-).

В вашем случае:

ffmpeg -i 01-Daemon.mp3 3>&2 2>&1 1>&3- | grep -i Duration

Проверяем:

$ ( echo "error" >&2; echo "output" ) 3>&2 2>&1 1>&3- | grep "error"
output
error

$ ( echo "error" >&2; echo "output" ) 3>&2 2>&1 1>&3- | grep -v "error"
output
6
23.11.2016, 15:59
3 ответа

Scroll вплоть до « Генерация имени файла » и включите либо extended_glob (что должно быть по умолчанию, но не для обратной совместимости), либо ksh_glob . И расширенные глобусы zsh, и ksh обладают всеми возможностями регулярных выражений.

ERE syntax      ksh glob      zsh extended glob
(foo)*          *(foo)        (foo)#
(foo)+          +(foo)        (foo)##
(foo)?          ?(foo)        (|foo)
(foo|bar)       @(foo|bar)    (foo|bar)

Имейте в виду, что большинство инструментов, использующих регулярные выражения, используют их как шаблоны поиска , которые должны соответствовать подстроке, но глобусы всегда используются как шаблоны, которые должны соответствовать всей строке. Например, foofoobar не соответствует zsh glob (foo) ## , поскольку после foofoo остается некоторый текст.

В Zsh есть дополнительные операторы, которые не расширяют выразительные возможности, но упрощают написание некоторых выражений. Операторы ^ и ~ ( extended_glob ) и ! (…) ( ksh_glob ) обеспечивают отрицание, например ^ foo или ! (Foo) соответствует чему угодно, кроме foo , что в синтаксисе регулярного выражения требует громоздкого | [^ f]. * | F [ ^ o]. * | fo [^ o]. * . Оператор <… -…> (специфично для zsh, не требует extended_glob ) соответствует любому целому числу (в десятичной системе счисления) в диапазоне, например <3-11> соответствует 3 и 10 , но не 30 или 1 .

Итак, исключая такие проблемы, как непечатаемые символы, ls | grep -e "ABC [0-9] \ +" можно записать такими способами, как

print -lr -- *ABC[0-9]##*(N)      # requires extended_glob
print -lr -- *ABC+([0-9])*(N)      # requires ksh_glob
print -lr -- *ABC+<->(N)

. Но поскольку «одна или несколько цифр, затем что угодно» эквивалентно «цифра, затем что угодно», это также может быть написано

print -lr -- *ABC[0-9]*(N)
3
27.01.2020, 20:23

При включенном extendedglob :

$ setopt extendedglob
$ print -rl -- perl[[:digit:]]##
perl5

или при включенном kshglob и отключенном bareglobqual :

$ setopt kshglob
$ unsetopt bareglobqual
$ print -rl -- perl+([[:digit:]])
perl5

Обратите внимание, что использование [: digit:] для сопоставления всех рассматриваемых цифр в текущей локали. Если вы хотите сопоставить только 0 - 9 , установите LC_ALL = C или используйте буквально [0123456789].


Вы можете указать количество совпадений, например, регулярное выражение {n, m} , используя (# cN, M) флаг подстановки в любом месте, где # и ## могут использоваться операторы, кроме (* /) # и (* /) ## :

$ print -rl -- perl[[:digit:]](#c1)
perl5
$ print -rl -- perl[[:digit:]](#c2)
zsh: no matches found: perl[[:digit:]](#c2)
3
27.01.2020, 20:23

Да, используйте ## , чтобы сопоставить одно или несколько вхождений [0-9] , например:

ABC[0-9]##

Для этого необходимо установить extendedglob , что по умолчанию. Если не установлено, сначала установите его:

setopt extendedglob

Пример:

% print -l ABC*
ABC
ABC75475
ABC8
ABC90

% print -l ABC[0-9]##
ABC75475
ABC8
ABC90
6
27.01.2020, 20:23

Теги

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