Можно ли переименовать PascalCase1.wav в kebab-case-1.wav с помощью одного регулярного выражения perl?

#regex #bash #perl #sh #regex-lookarounds

#регулярное выражение #bash #perl #sh #поиск регулярных выражений

Вопрос:

Вот пример моих данных:

 SomePascalCase.wav
ThingsThat1.wav
Are.wav
Here.wav
 

Вот результат, который я ищу:

 some-pascal-case.wav
things-that-1.wav
are.wav
here.wav
 

Вот что я использовал:

 for f in *.wav; do
   mv "$f" $(
      echo "$f" |
      perl -pe 's/([A-Z])([a-z] )(?=[0-9A-Z])/L12-/g' |
      perl -pe 's/([A-Z])([a-z] )(?=.wav)/L12/g'
   )
done
 

Возможно ли объединить два регулярных выражения, которые я использовал, в одно?

Комментарии:

1. Вы не должны использовать 1 and 2 в выражении замены; вы должны использовать $1 and $2 .

2. IIRC, perl RES завершены по Тьюрингу, поэтому вы можете делать буквально все, что угодно, одним RE. Если вы, хотя … конечно, это совсем другой вопрос.

3. В вашем шаблоне есть ошибка. Вы хотите .wav , а не .wav

Ответ №1:

На самом деле вы бы не использовали здесь подстановку регулярных выражений. Вы бы использовали split , а затем join с тире. split Шаблон представляет собой отрицательный взгляд назад, за которым следует взгляд вперед.

 lc join "-", split /(?<=[a-z])(?=[A-Z])/;

 

Например

 pp split /(?<=[a-z])(?=[A-Z])/, "FooBarBaz"

("Foo", "Bar", "Baz")

 

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

 pp split /(?<=[a-z])(?=[A-Z])|(?<=[A-Za-z])(?=[d])|(?<=[d])(?=[A-Za-z])/, "Foo1BarBaz1"

("Foo", 1, "Bar", "Baz", 1)

 

Редактировать
Чтобы включить это в свой один лайнер, вы должны сделать это:

 f=FooBarBaz1
echo $( echo "$f" | perl -pe '$_ = lc join "-", split /(?<=[a-z])(?=[A-Z])|(?<=[A-Za-z])(?=[d])|(?<=[d])(?=[A-Za-z])/;' )

foo-bar-baz-1

 

Выполнение этого с заменами только усложнит задачу.

HTH

Комментарии:

1. ни одна из этих команд не работает в bash или zsh. я также хочу использовать s/pattern/replacement/, так что это не отвечает на мой вопрос.

2. Я обновил ответ, чтобы использовать вашу командную строку.

3. Если вы хотите использовать что-то подобное pp , расскажите людям, что это такое. Поскольку вы просто печатаете здесь список, я не вижу преимущества в дополнительных, неосновных материалах Perl.

4. Я не согласен с вами в этом, но я просто оставил это, потому что это была просто иллюстрация.

Ответ №2:

Я понимаю ваши требования:

  • Он должен работать bash как однострочный.
  • Он преобразует строку имени файла с помощью одного s / pattern / replacement / operator .

Тогда как насчет:

 for f in *.wav; do mv "$f" "$(echo "$f" | perl -pe 's/(^|[a-z])([A-Z0-9])/ $1 eq "" ? lc($2) : $1 . "-" . lc($2) /ge')"; done
 
  • e Опция для s/pattern/replacement/ оператора позволяет замене быть выражением perl .

Комментарии:

1. Спасибо! я не знал, что вы можете использовать sprintf в подобном регулярном выражении perl. аккуратно!

2. ДА. Я добавил краткое объяснение этой e опции. BR.

3. s/.../.../ в основном это сокращение от s/.../ "..." /e . Вы можете поместить любой код в выражение замены (не в регулярное выражение).

4. Это sprintf было совершенно бесполезно, поэтому я удалил его.

Ответ №3:

 perl -pe 's/([A-Z])([a-z] )(?=[0-9A-Z])/L12-/g' |
perl -pe 's/([A-Z])([a-z] )(?=.wav)/L12/g'
 

может быть уменьшен до почти эквивалентного

 perl -pe's/[a-z]K[A-Zd]/-$amp;/g; s/[A-Z]/L$amp;/g'
 

или просто

 perl -pe's/[a-z]K[A-Zd]/-$amp;/g; $_=lc'
 

(Технически, вы даже можете удалить это пространство.)

Например,

 $ echo FooBar1.wav | perl -pe's/[a-z]K[A-Zd]/-$amp;/g; $_=lc'
foo-bar-1.wav
 

Для 100% эквивалентности вам потребуется

 perl -pe's/([A-Z][a-z] )(?:(?=[A-Zd])|(?=(.wav)))/ "L$1" . ( $2 ? "" : "-" ) /eg'
 

(Вы даже можете удалить все эти пробелы.)

Например,

 $ echo ABCdef.wav | perl -pe's/([A-Z][a-z] )(?:(?=[A-Zd])|(?=(.wav)))/ "L$1" . ( $2 ? "" : "-" ) /eg'
ABcdef.wav
 

Ответ №4:

Если нужно получить это внутри одной команды подстановки, это можно сделать следующим образом:

 perl -pe 's/. ?(?=[A-Z0-9.])/($i  ?"-":"").lc$amp;/ge'
 

Это соответствует любому набору символов, за которым следует заглавная, цифра или точка. Условие проверяет, является ли это первым совпадением или более поздним. Если более позднее, оно добавляет дефис к версии в нижнем регистре соответствующей подстроки.