Ответ 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!)
Дополнительная информация:
-
При отложенном расширении:
-
При замене подстроки: