Удалить вещи, получить номера, получить текст с пробелами вместо точек, удалить остальные - PullRequest
2 голосов
/ 27 февраля 2010

Это мой первый вопрос, так что я надеюсь, что я не слишком возился с заголовком и форматированием.

У меня есть набор файлов, которые мой клиент отправил мне в этой форме:

Name.Of.Chapter.021x212.The.Actual.Title.Of.the.Chapter.DOC.NAME-Some.stuff.Here.ext

Мне нужно регулярное выражение для вывода просто:

212 Фактическое название главы

Я не собираюсь использовать его с каким-либо конкретным языком сценариев; это пакетное переименование файлов через приложение, поддерживающее регулярные выражения (которое уже «сохраняет» расширение).

Пока все, что я смог сделать, это:

/.*x(\d+)\.(.*?)\.[A-Z]{3}.*/ -->REPLACE: $1 $2

(Захватывать все перед числом, которому предшествует «x», номера групп после «x», группировать все, что следует, пока не встретится трехзначное заглавное слово, а затем записать все, что следует за ним)
что возвращает мне:

212 The.Actual.Title.Of.the.Chapter

Увидев результат, я подумал, что-то вроде:

/.*x(\d+)\.([^.]*?)\.[A-Z]{3}.*/ -->REPLACE: $1 $2

(Измените вторую группу на «Захватить все , которое не является точкой ...») работало бы так, как ожидалось. Вместо этого все регулярные выражения не могут полностью соответствовать.

Чего мне не хватает?

ТИА

CIA
эля

Ответы [ 3 ]

2 голосов
/ 27 февраля 2010

.*x(\d+)\. совпадений Name.Of.Chapter.021x212.

\.[A-Z]{3}.* совпадений .DOC.NAME-Some.stuff.Here.ext

Но ([^.]*?) не соответствует The.Actual.Title.Of.the.Chapter, поскольку это регулярное выражение вообще не допускает периодов.

1 голос
/ 28 февраля 2010

На ваш вопрос "Как я могу удалить точки в процессе сопоставления?" Ответ: «Вы не можете». Единственный способ сделать это - обработать результат матча на втором шаге, как говорили другие. Но я думаю, что есть более простой вопрос, который необходимо решить, а именно: «Что это значит, что регулярное выражение соответствует заданному входу?»

Регулярное выражение обычно считается совпадающим со строкой, когда оно описывает любую подстроку этой строки. Если вы хотите быть уверены, что регулярное выражение описывает всю строку, вам нужно добавить начальный (^) и конечный ($) якоря:

/^.*x(\d+)\.(.*?)\.[A-Z]{3}.*$/  

Но в вашем случае вам не нужно описывать всю строку; если вы избавитесь от .* на обоих концах, это также подойдет вам:

/x(\d+)\.(.*?)\.[A-Z]{3}/  

Я рекомендую вам не привыкать к "регулярным выражениям" регулярных выражений с .* в начале и в конце. В частности, ведущий .* может неожиданно изменить поведение регулярного выражения. Например, если во входной строке есть два места, в которых может совпадать x(\d+)\., ваше "настоящее" совпадение начнется со второго. Кроме того, если он не связан с ^ или \A, ведущий .* может сделать все регулярное выражение гораздо менее эффективным.

Я сказал «обычно» выше, потому что некоторые инструменты автоматически «привязывают» совпадение в начале (match() в Python) или на обоих концах (matches() в Java), но это довольно редко. Большинство оболочек и инструментов командной строки, доступных в * nix-системах, определяют соответствие регулярному выражению традиционным способом, но на всякий случай стоит сказать, какие инструменты вы используете.

Наконец, пару слов о словаре. Скобки в (\d+) означают, что соответствующие символы записываются , а не сгруппированы . Многие разновидности регулярных выражений также поддерживают не захватывающие скобки в форме (?:\d+), которые используются только для группировки . Говорят, что любой текст, включенный в общее совпадение, независимо от того, захвачен он или нет, был использован (не захвачен ). То, как вы использовали слова «захват» и «группа» в своем вопросе, гарантированно вызовет максимальную путаницу у любого, кто предполагает, что вы знаете, о чем говорите. : D

Если вы еще не читали его, ознакомьтесь с этим превосходным учебником .

1 голос
/ 27 февраля 2010

поскольку вы находитесь на Mac, вы можете использовать оболочку

$ s="Name.Of.Chapter.021x212.The.Actual.Title.Of.the.Chapter.DOC.NAME-Some.stuff.Here.ext"

$ echo ${s#*x}
212.The.Actual.Title.Of.the.Chapter.DOC.NAME-Some.stuff.Here.ext

$ t=${s#*x}

$ echo ${t%.[A-Z][A-Z][A-Z].*}
212.The.Actual.Title.Of.the.Chapter

Или, если вы предпочитаете sed, например,

echo $filename | sed 's|.[^x]*x||;s/\.[A-Z][A-Z][A-Z].*//' 

Для обработки нескольких файлов

for file in *.ext
do
  newfile=${file#*x}
  newfile=${newfile%.[A-Z][A-Z][A-Z].*}
  # or 
  # newfile=$(echo $file | sed 's|.[^x]*x||;s/\.[A-Z][A-Z][A-Z].*//')
  mv "$file" "$newfile"
done 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...