Многозначные диапазоны файлов в лексикографическом порядке в zsh


24

Я хотел бы указать диапазон файлов (в лексикографическом порядке) с двумя целыми числами (например, от 2 до 57) в zsh путем глобализации.

Например: «выберите файлы с 2 по 57 в лексикографическом порядке по пути, соответствующему некоторому шаблону сглаживания».

Я думал, что квадратные скобки сделают это

 for x in /foo/bar/*[2-57]; do print $x; done

но ЗШ , видимо , думает , что я прошу за файлы 2к 5(или что - то подобное) , а не файлы 2в 57. Есть мысли почему? Как я могу сделать это?

Ответы:


30

[2-57]представляет собой набор символов , состоящий из 2, 3, 4, 5и 7, в Zsh и любой другой шаблона и синтаксисе регулярных выражений там. Ваш шаблон глобуса *[2-57]соответствует каждому имени файла, последний символ которого является одной из этих пяти цифр.

Я думаю, вы неправильно помните синтаксис [m,n] квалификатора глобуса . Определители глобуса всегда заключаются в круглые скобки в конце шаблона, а разделитель диапазона - запятая. Шаблон *([2,57])расширяется до 2-го, 3-го,…, 57-го матчей. Порядок расширения по умолчанию - лексикографический (с некоторым специальным волшебством, чтобы сортировать числа в числовом порядке, если numeric_glob_sortопция установлена); Вы можете управлять им с помощью спецификатора oor Oglob (например, *(om[2,57])чтобы соответствовать 57 самым последним файлам, кроме одного самого последнего файла).

for x in /foo/bar/*([2,57]); do print $x; done

Не то, что вы просили, а связанное и, возможно, полезное для будущих читателей: если вы хотите перечислить файлы со 2 по 57, независимо от того, существуют они или нет, вы можете использовать выражение для фигурной скобки . Эта функция также существует в bash и ksh.

echo hello{2..57}

И если вы хотите сопоставить файлы, имя которых содержит число от 2 до 57, вы можете использовать шаблон <2-57>. Это специфично для Zsh.

$ ls
file1 file2 file3 file57 file58
$ echo file<2-57>
file2 file3 file57

Обратите внимание, что шаблон, как *<2-57>, вероятно, не будет делать то, что вы ожидаете, потому что *может совпадать с цифрами. Например, file58совпадает *<2-57>с file5соответствием *части и 8соответствием <2-57>части. Шаблон *[^0-9]<2-57>избегает этой проблемы.


Вы правы. Я неправильно запоминал глобус-квалификатор. Спасибо за тщательное объяснение.
Амелио Васкес-Рейна

Кстати, это утверждение меня немного смутило if you want to enumerate files 2 to 57 whether they exist or not, you can use a range brace expression. Если файлы не существуют и совпадений нет, как расширение скобки узнает, как его расширить? (как бы он расширился иначе, чем глобальный квалификатор?)
Амелио Васкес-Рейна

2
@intrpc foo{8..11}barрасширяется до foo8bar foo9bar foo10bar foo11bar. Этот бит расширения не связан с именами файлов. Аналогично, foo{eight,nine,ten,eleven}barрасширяется до fooeightbar fooninebar footenbar fooelevenbar. Это расширение скобок в ksh / bash / zsh.
Жиль "ТАК - перестань быть злым"

6

но zsh, видимо, думает, что я прошу файлы от 2 до 5 (или что-то в этом роде) вместо файлов от 2 до 57. Есть мысли почему?

Поскольку []квадратные скобки указывают список совпавших символов (которые могут быть цифрами), а не числа интерпретируются математически. Такой шаблон сопоставляется с одним символом. Список может содержать диапазоны, но из цифр или букв. [2-57]матч расширяется до «Все цифры в диапазоне от 2 до 5 и .

Чтобы сопоставить числа от 2 до 57, было бы проще использовать выражение последовательности вместо шаблона слияния (или вместе с ним):

for x in /foo/bar/*{2..57}; do print $x; done

Изменить : Но это, к сожалению, не даст вам лексикографический порядок всех перечисленных файлов - они будут сгруппированы по общим числам окончания из-за расширения оболочки.


Спасибо @rozcietrzewiacz! Я должен был подумать об этом. В моих файлах были номера, так что на мгновение я подумал, что []печатал вещи по порядку ...
Амелио Васкес-Рейна

Ваше объяснение [2-57]верно, но я не думаю {2..57}(что вы имели в виду, верно?) Имеет отношение к тому, что хочет сделать intrpc, а именно: «выберите файлы со 2 по 57 в лексикографическом порядке».
Жиль "ТАК - перестань быть злым"

Спасибо за редактирование (наверное, пора идти спать). И ты прав - я забыл про лексикографическую часть заказа .
rozcietrzewiacz
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.