Замена второго вхождения «-» на «_» с помощью Powershell - PullRequest
0 голосов
/ 16 ноября 2018

Я использую Powershell для упрощения повторяющихся задач при создании каталогов, переименовании и перемещении файлов. Я работаю с видео и PDF файлами, где необходимый синтаксис имени файла очень специфичен. До сих пор мне удавалось исправить все распространенные ошибки, с которыми я сталкиваюсь, но эта ошибка меня озадачила.

Правильный синтаксис для моих файлов будет включать:

01A-50_02A-50-CIPP-PRE.MP4
01AA-50_02AA-50-CIPP-PNSL.PDF
W01AA-48_02AA-48-CIPP-PST-CMP.MPG

Я получаю большое количество файлов, которые выглядят так:

01A-50-02A-50-CIPP-PRE.MP4
01AA-50-02AA-50-CIPP-PNSL.PDF
W01AA-48-02AA-48-CIPP-PST-CMP.MPG

Мне нужно заменить вторую черту подчеркиванием, оставляя другие штрихи без изменений. В противном случае я могу сделать это оптом с некоторой помощью из Excel, но я надеялся получить короткий код, который мог бы найти и исправить эту ошибку в синтаксисе без необходимости экспортировать список в Excel, использовать текст в столбцы, а затем объединить алфавитно-цифровые порции обратно вместе. Я также не хочу исправлять все эти имена файлов вручную.

Из того, что я исследовал, невозможно нацелить конкретное вхождение персонажа на замену. ближе всего я подумал, что нашел решение, включающее REGEX, определение и замену шаблона. Я не смог ничего с этим поделать.

Я бы использовал этот код, открыв папку, содержащую пропущенные файлы, открыв там окно Powershell, скопировав код из txt-файла на моем рабочем столе и вставив его в Powershell.

Любая помощь по этому вопросу будет принята с благодарностью.

Ответы [ 5 ]

0 голосов
/ 16 ноября 2018

Спасибо, Соломон Уко!Это было почти то, что я искал.

Get-ChildItem |Rename-Item -NewName {$ .name -replace '(? <= (^ | \ N) [^ -] * - [^ -] *) -', '</em>'}

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

"E21U-50A_E21U_50-CIPP-PST-CMP"

вместо

"E21U-50A_E21U-50-CIPP-PST-CMP"

исправить это было достаточно просто.
Все, что я сделал, это сначала заменил все _ с - с.

Get-ChildItem | Rename-Item -NewName {$_.name -replace '_','-'}

Get-ChildItem | Rename-Item -NewName {$_.name -replace '(?<=(^|\n)[^-]*-[^-]*)-','_'}

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

0 голосов
/ 16 ноября 2018

Используйте оператор -replace с регулярным выражением:

Get-ChildItem |
  Rename-Item -NewName { $_.Name -replace '^([^_-]+-[^_-]+)-', '$1_' } -WhatIf

-WhatIf предварительный просмотр операции переименования; удалите его для фактического переименования.

  • Regex '^([^_-]+-[^_-]+)-' захватывает первые два - разделенных токена в начале (^) имени файла, используя группу захвата ((...)) для захвата токенов, исключая 2-й - .

    • [^_-]+ фиксирует любой непустой набор символов, которые не являются ни -, ни _. _ также исключается для предотвращения ложных срабатываний с именами файлов, которые уже являются правильными; для тех, кто не исключает, _ будет соответствовать первым 3 токенам и вставит туда дополнительные _.
  • Операнд-заменитель $1_ затем использует значение 1-й (и единственной) группы захвата ($1), за которым следует литерал _, чтобы заменить то, что соответствует регулярному выражению, которое фактически заменяет 2-е - с _.

  • Если указанное имя файла не соответствует регулярному выражению (если оно уже правильно), имя возвращается как есть, что является тихим запретом в контексте Rename-Item.

0 голосов
/ 16 ноября 2018

А как насчет этого RegEx: (?<=(^|\n)[^-]*-[^-]*)-?

Или как полная команда (используя ответы на Заменить часть имени файла Powershell ):

Get-ChildItem | Rename-Item -NewName {$_.name -replace '(?<=^[^-_]+-[^-_]+)-','_'}

Редактировать: включены предложения от @ mklement0

0 голосов
/ 16 ноября 2018

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

$name = '01A-50-02A-50-CIPP-PRE.MP4'
$first,$second,$rest = $name -split '-',3
$newName = "${first}-${second}_${rest}"
0 голосов
/ 16 ноября 2018

Глядя на ваши примеры, кажется, что второе - всегда появляется между числами. Что-то вроде $Variable -replace 'REGEX','_'

Использование приведенного ниже регулярного выражения будет соответствовать.

(?<=[0-9])(.)(?=[0-9])

() создает группу для сопоставления, это группа захвата.

?<= является положительным взглядом сзади, он соответствует группе перед основным выражением без включения его в результаты

[0-9] - это набор символов, соответствующий любому значению от 0 до 9.

. соответствует любому символу, кроме разрывов строк

?= является положительным прогнозом, он соответствует группе после основного выражения, не включая его в результаты

Я рекомендую использовать Regexr для проверки и изучения Regex.

...