3

Я пытаюсь вручную извлечь дайджесты из ресурсов Rails (не спрашивайте). Я был направлен в ZMV для простого поиска / замены на основе регулярных выражений. Но обычный {32} синтаксис для указания количества повторений не работает:

$ zmv -n '(**/)(*)' '$1${2//-[A-Za-z0-9]\{32\}/}'

Я пробовал некоторые другие форматы. Это, например, работает, но слишком жадно (например, image-3.png 3.png превратится в image.png ):

$ zmv -n '(**/)(*)' '$1${2//-[A-Za-z0-9]##\./.}'

Этот синтаксис двойного хеширования обнаружился только после большого количества Google (я бы ожидал +). Но я не могу на всю жизнь найти, как заставить {32} работать. Я пробовал #32#? Который, казалось, работал, но это потому, что он читал это как (в моих глазах) ?32? и это означает, что он встретил все, что было три в дайджесте или последний символ.

Как я могу обозначить повторение символов в ZMV?

РЕДАКТИРОВАТЬ:

Видимо, это поможет некоторым просматривать имена файлов, которые я пытаюсь сопоставить? Для ясности: мой вопрос "как я обозначаю повторение символов в zmv", а не "как мне сопоставить эти имена файлов" (вопрос, на который я знаю ответ в стандартном формате RegEx). Если это поможет, вот мое предназначение до и после:

directory/asset-jej4jtifne9bjkkeuwr09rewrewlur23.css
another-directory/style-748reiodlpqwerntaerwerwerexfzsdf.js.gz
directory/subdirectory/this-is-a-thing-qwertyuiopasdfghjklzxcvbnm123456.js
third-directory/should-not-match-3.css

Должно стать:

directory/asset.css
another-directory/style.js.gz
directory/subdirectory/this-is-a-thing.js
third-directory/should-not-match-3.css

ВТОРОЙ РЕДАКТИРОВАТЬ:

Поскольку мне нужно было сделать это вчера, я проделал долгий путь и (как и ожидалось) это сработало. Я все еще хотел бы знать, как избежать этого в будущем. Вот команда, которую я использовал в итоге (я повторил свой совпадение символов 32 раза явно):

$ zmv '(***/)(*)' '$1${2//-[A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9]/}'

Третье редактирование:

Для записи, я использую zsh на OS X. Я полагаю, что zmv одинаково для разных платформ, но я не могу сказать наверняка.

2 ответа2

5

Оболочки в основном не обеспечивают обычный синтаксис регулярных выражений, а являются шаблонами подстановки «glob». Основные подстановочные знаки оболочки не так мощны, как регулярные выражения; Например, регулярное выражение .* (любая последовательность символов) эквивалентно шаблону glob * но регулярное выражение a* (любая последовательность a ) не имеет эквивалента шаблона glob в простом sh. См. Почему мое регулярное выражение работает в X, а не в Y? для обзора основных различных синтаксисов регулярных выражений / шаблонов.

Zsh имеет расширенные шаблоны глобуса zsh, которые обеспечивают ту же выразительную силу, что и регулярные выражения, но с другим синтаксисом. Эти шаблоны автоматически включаются в zmv и в функциях завершения, но в других местах в zsh их нужно явно включить с помощью setopt extended_glob (поместите это в ваш .zshrc - единственная причина, по которой он не используется по умолчанию, - обратная совместимость с древними версиями zsh). ).

Существует синтаксис повторения N раз, но он немного скрыт, он отображается под флагами глобализации, а не в списке операторов. Это флаг c , который должен использоваться один, за которым следует номер повторения (или два числа через запятую, чтобы задать диапазон).

zmv -n '(**/)(*)' '$1${2//-[A-Za-z0-9](#c32)/}'
1

Я не могу заставить его работать с zmv либо. Должен быть способ, но он ускользает от меня. Тем не менее, zmv не единственный инструмент, который может сделать что-то подобное. Вы также можете использовать rename .

  • Если вы используете zsh

    $ rename -n 's/-[A-Za-z0-9]{32}//' **/* 
    another-directory/style-748reiodlpqwerntaerwerwerexfzsdf.js.gz renamed as another-directory/style.js.gz
    directory/asset-jej4jtifne9bjkkeuwr09rewrewlur23.css renamed as directory/asset.css
    directory/subdirectory/this-is-a-thing-qwertyuiopasdfghjklzxcvbnm123456.js renamed as directory/subdirectory/this-is-a-thing.js
    
  • Если вы используете bash

    $ shopt -s globstar 
    $ rename -n 's/-[A-Za-z0-9]{32}//' **/* 
    another-directory/style-748reiodlpqwerntaerwerwerexfzsdf.js.gz renamed as another-directory/style.js.gz
    directory/asset-jej4jtifne9bjkkeuwr09rewrewlur23.css renamed as directory/asset.css
    directory/subdirectory/this-is-a-thing-qwertyuiopasdfghjklzxcvbnm123456.js renamed as directory/subdirectory/this-is-a-thing.js
    

Обратите внимание, что в мире Linux есть две команды rename . В приведенных выше примерах используется Perl, который используется по умолчанию в дистрибутивах на основе Debian.


Причина, по которой вы не можете заставить это работать с zmv заключается в том, что i) это не zmv интерпретирует выражение, это особенность оболочки и, следовательно, ii) это вовсе не регулярное выражение, это глобус.

Когда вы запускаете команду в своем вопросе, zmv устанавливает $2 для каждого из имен файлов, а затем это оболочка, которая выполняет замену (${2//...). После того как переменная была расширена оболочкой, она возвращается в zmv которая пытается выполнить операцию переименования.

Как и оболочка korn и bash, zsh поддерживает формат ${foo//bar} , который удалит все совпадения с глоб- bar из переменной $foo (сопоставьте это с ${foo/bar} который удалит только первое совпадение), Это работает так:

% foo="Xababab"
% echo ${foo//ab}
X
% echo ${foo//a*b}
X

Как вы можете видеть выше, шаблоны - это глобусы, а не регулярные выражения. Глобус a*b означает «соответствует a , затем 0 или более символов и затем b ». Это эквивалент этого регулярного выражения: a.*b Глобусы, в отличие от регулярных выражений, не поддерживают повторение (Очевидно, что у Zsh'ов есть, см . Ответ Жиля). Синтаксис x{n} не будет соответствовать n повторениям x. Вот почему ваше регулярное выражение потерпело неудачу: его вообще не интерпретировали как регулярное выражение!

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .