Я пытаюсь повторить команду Perl из этого ответа на Ask Ubuntu в среде командной строки Windows. Я полагаю, что я скачал Perl для Windows и установил его правильно, поэтому ошибка, кажется, одна из синтаксиса.

Исходная команда в оболочке Linux:

ls | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/' . filename.csv

Я считаю, что версия для Windows должна быть:

dir > perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/' >> filename.csv

Тем не менее, это ошибка, которую я получаю:

Invalid switch - "(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg".
'/'' is not recognized as an internal or external command,
operable program or batch file.

Какой правильный синтаксис для запуска этой команды Perl в Windows?

2 ответа2

3

Другой ответ не верен. Если вы сделаете это, вы все равно получите ошибки при запуске в cmd

C:\Users>dir | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/'
Can't find string terminator "'" anywhere before EOF at -e line 1.
'/'' is not recognized as an internal or external command,
operable program or batch file.

Причина заключается в нескольких проблемах в команде

Даже / иногда разделяет аргументы команды, такие как dir/b/c/d или yourcommand/param но, к счастью, это не применимо в этом случае. Итак 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/' передан в качестве нескольких параметров , если есть какие - либо разделитель слов в нем, что в этом случае, и команда будет эквивалентна

perl  -pe  's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2   $3-$4-$5   $6   $   & /'

и предложенная вами команда dir > perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/' >> filename.csv будет проанализирован как

>>filename.csv >perl dir -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2  $3-$4-$5  $6  $ & /'

Поскольку >file перенаправление файла может появиться в любом месте. Это приводит к Invalid switch - "(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg" вы видели выше, потому что это недопустимый переключатель в dir

Это также причина, по которой есть ошибка в perl. Can't find string terminator "'" anywhere before EOF at -e line 1 кроме строк из cmd, потому что в первом параметре начинается с ' но закрытия нет ' . Легко проверить, как он разбивается на параметры:

E:\>type testparam.bat
@echo off
:loop
if "%1"=="" goto :exit
echo "%1"
shift
goto :loop
:exit

E:\>testparam -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/'
"-pe"
"'s/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2"
"$3-$4-$5"
"$6"
"$"
'/'' is not recognized as an internal or external command,
operable program or batch file.

Теперь посмотрите на вывод и обратите внимание на забавные вещи: из-за амперсанда &/' завершит предыдущую команду и выполнит команду с именем /' которая не существует, и выдаст ошибку, как указано выше


Лучшее решение - использовать PowerShell, где вы можете выполнить команду с небольшим изменением, потому что для цитирования в PowerShell также используется одинарная кавычка.

ls |% { $_.Name } | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/'

ls вместе с dir и gci в псевдониме PowerShell для Get-ChildItem . И вам нужно |% (это псевдоним ForEach-Object) для печати имен объектов. Альтернативой в PowerShell является

cmd /c dir | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/'

Я пропустил перенаправление для ясности. Вывод будет распечатан на стандартный вывод. Если вы хотите перенаправить его в файл, просто добавьте >filename.csv или >>filename.csv зависимости от того, хотите ли вы перезаписать или добавить

Выполнение команды в cmd было бы намного более проблематичным (и новый код должен использовать PowerShell в любом случае, так как он долгое время имел параметры по умолчанию)

dir | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2^,$3-$4-$5^,$6^,$^&^/'

В этом случае изменение ' на " также работает, но оно быстро сломается во многих других ситуациях

dir | perl -pe "s/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/"

Обратите внимание, что даже в Linux ваша команда также неверна

ls | perl -pe 's/(.)(.*)_(\d{4})(\d{2})(\d{2})_(\d+).jpg/\u$1$2,$3-$4-$5,$6,$&/' . filename.csv

Вам нужно >filename.csv вместо . filename.csv

1

Windows использует | как персонаж трубы тоже. Скопируйте команду напрямую, но замените ls на dir а filename на cost.csv.

Добавлен как ответ, потому что у меня нет репутации комментировать

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