Как заменить строку внутри файла bat с помощью строки параметров командной строки

У меня есть следующее в командном файле cmd:

for /f %%l in (%2) do (for %%f in (%%l) do copy "%%f" %1))

Примечание: в этом случае script читается текстовый файл, содержащий файл txt с разделителями с запятой, путь которого задается% 2 (например, который содержит c:\test1\file1.cs; d:\file2.js) и скопируйте файлы в папку назначения, указанную% 1.

Мне нужно заменить строковое значение %1 параметра x (которое также передается в пакетный файл, например %3), с %4 значением, которое также передается как параметр в пакетный файл.

например:

if %1 = 'test replace x with y'
%3=x
%4=y

поэтому выход должен быть "test replace y с y"

Как я могу добиться этого с помощью пакетного интерпретатора Windows CMD?

Ответ 1

Прежде всего, вам нужно будет сохранить %1 в переменной, после чего вы сможете выполнить замены.

В принципе, синтаксис замены заключается в следующем:

%variable:str1=str2%

что означает: "заменить каждый str1 на variable на str2 '.

В вашем случае оба str1 и str2 являются параметрами, а не буквальными строками. Используя приведенный выше шаблон напрямую, вы можете получить это выражение:

%variable:%3=%4%.

Но это путало бы парсер, поскольку он не знал бы, что сначала следует оценивать %3 и %4. Фактически, сначала попытаться оценить %variable:% (и выйти из строя).

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

ECHO %var% == > CALL ECHO %%var%%.

Обратите внимание на двойную % s. Во время разбора их оценивают до одного % s. Полученная команда будет снова проанализирована CALL, и конечный эффект будет таким же, как в случае исходной команды ECHO %var%.

Таким образом, он работает так же, как и исходная команда (что хорошо), и то, что мы получаем здесь, - это более поздний момент оценки, я имею в виду окончательную оценку, когда переменная фактически заменяется ее значением. Зная об этом эффекте, мы можем построить наше выражение таким образом, чтобы сначала оценивались %3 и %4, а затем все полученное выражение. В частности, вот так:

%%variable:%3=%4%%

После первого анализа это выражение будет выглядеть примерно так:

%variable:x=y%

Это будет проанализировано снова, и выход будет variable измененным содержимым.

Для лучшей иллюстрации здесь приведен простой рабочий пример:

SET "output=%1"
CALL SET output=%%output:%3=%4%%
ECHO %output%

UPDATE

Есть еще один способ сделать то же самое, о чем я, вероятно, должен был упомянуть первым.

Командная оболочка Windows поддерживает надлежащее замедленное расширение. Он проще в использовании, но имеет некоторые оговорки.

Во-первых, как его использовать. Синтаксис для замедленного расширения !var! вместо %var% для немедленного расширения (который остается действительным и может использоваться вместе с синтаксисом замедленного расширения).

Вероятно, !var! не будет работать в вашем script, пока вы не включите синтаксис с помощью команды:

SETLOCAL EnableDelayedExpansion

Команда ENDLOCAL закрывает блок, в котором синтаксис с задержкой расширения действителен и интерпретируется командной оболочкой.

Приведенный выше пример script можно переписать следующим образом:

SET "output=%1"
SETLOCAL EnableDelayedExpansion
SET output=!output:%3=%4!
ECHO !output!
ENDLOCAL

Итак, как это работает в случае команды SET output=!output:%3=%4!:

  • %3 и %4 оцениваются немедленно, то есть во время разбора - они заменяются на x и y соответственно;

  • команда становится следующей: SET output=!output:x=y!;

  • команда собирается выполнить - выражение ! оценивается (x заменяется на y s);

  • выполняется команда - изменена переменная output.

Теперь о предостережениях. Первое, что нужно помнить, это то, что ! становится частью синтаксиса и потребляется и интерпретируется всякий раз, когда встречается. Поэтому вам нужно будет избежать этого, когда вы хотите использовать его как литерал (например, ^!).

Другой оговоркой является основной эффект блока SETLOCAL/ENDLOCAL. Дело в том, что все изменения переменных среды внутри такого блока, ну, локальные. После выхода из блока (после выполнения ENDLOCAL) переменная устанавливается в значение, которое было до ее ввода (до выполнения SETLOCAL). Это означает, что измененное значение output будет действительным только в блоке SETLOCAL, который вы должны были инициировать для использования замедленного расширения в первую очередь. Возможно, это не может быть проблемой в вашем конкретном случае, если вам просто нужно изменить значение, а затем использовать его сразу, но вам, вероятно, придется помнить его в будущем.

Примечание. Согласно комментарию jeb, вы можете сохранить измененное значение и оставить блок SETLOCAL с помощью этого трюка:

ENDLOCAL & SET "output=%output%"

Оператор & просто ограничивает команды, когда они помещаются в одну строку. Они выполняются один за другим, в том же порядке они указаны. Дело в том, что к моменту разбора строки блок SETLOCAL еще не оставлен, поэтому %output% оценивает модифицированное значение, которое остается в силе. Но назначение действительно выполняется после ENDLOCAL, то есть после выхода из блока. Таким образом, вы эффективно сохраняете измененное значение после выхода из блока, тем самым сохраняя изменения. (Спасибо, jeb!)


Дополнительная информация:

Ответ 2

Я попробовал под кодом в пакетном файле Windows 7:

SET output=%1
CALL SET output=%output:unsigned=signed%
CALL SET output=%output:.apk=-aligned.apk%

Это работает!

Ответ 3

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

SET "output1=%1"
CALL SET output1=%%output1:%3=%4%%
for /f "tokens=1" %%a in ('echo %output1%') do set output2=%%a
CALL SET output2=%%output2:%5%6%
for /f "tokens=1" %%a in ('echo %output2') do set output3=%%a