Как заменить строку внутри bat-файла на строку параметров командной строки - PullRequest
13 голосов
/ 28 апреля 2011

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

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

примечание: этот скрипт в основном выполняет чтение текстового файла, который содержит текстовый файл с разделителями-точками с запятой, путь которого определяется% 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замените y на y '

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

Ответы [ 3 ]

50 голосов
/ 28 апреля 2011

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

По сути, синтаксис для замены таков:

%<i>variable</i>:<i>str1</i>=<i>str2</i>%

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

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

%variable:%3=%4%.

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

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

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

Обратите внимание на двойные % с. Во время анализа они оцениваются как единичные % с. Полученная команда будет снова проанализирована 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! не будет работать в вашем скрипте, пока вы не включите синтаксис командой:

SETLOCAL EnableDelayedExpansion

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

Приведенный выше пример сценария можно переписать так:

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 с);

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

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

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

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

ENDLOCAL & SET "output=%output%"

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


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

  1. При отложенном расширении:

  2. При замене подстроки:

1 голос
/ 21 ноября 2014

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

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

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

0 голосов
/ 30 января 2014

Если вам нужно заменить несколько параметров в одной строке, просто используйте «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
...