@ECHO OFF
SETLOCAL
:: remove variables starting $
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
:: set up substitution elements from replacements.txt
FOR /f "delims=" %%a IN (replacements.txt) DO SET "$%%a"
(
FOR /f "tokens=1*" %%a IN (q21450455.txt) DO CALL :rep1 %%a "%%b"
)>newfile.txt
GOTO :EOF
:rep1
IF defined $%1 (CALL SET "newword=%%$%1%%") ELSE (SET newword=%1)
ECHO %newword% %~2
GOTO :eof
Нет, что легко следовать - так я объясню.
Сначала выполняется команда set $
, в которой будут «перечислены» любые переменные, начинающиеся $
, один на строку в формате $alreadyset=previousvalue
. 2^>nul
гарантирует, что сообщение об ошибке (Environment variable $ not found
) не отображается. Карет (^
) сообщает cmd
, что перенаправитель >
является частью строки, которая должна быть выполнена, а не FOR
.
Таким образом, для каждой строки вывода (если таковые имеются), for /f
tokenises линию так, что каждый [ряд] =
символов (символ [Set] bewteendelims=
и "
) является «маркер разделителя» , Токен 1 применяется к метастабильному (%%a
в этом случае). Можно назначить последовательность токенов, которые затем применяются к следующим метапеременным.
так, $alreadyset=previousvalue
является tokenised к $alreadyset
и previousvalue
и $alreadyset
присвоенного %%a
; команда set
устанавливает %%a
в пустую строку, поэтому $alreadyset
устанавливается в пустую строку и, следовательно, удаляется из среды.
Синтаксис set "var=value"
используется для обеспечения того, чтобы любые конечные пробелы на линии были , а не, включенные в присвоенное значение. Пробелы немного трудно увидеть ...
Следующая FOR /F
не использует разделители (без символов между =
и "
), который переопределяет разделитель по умолчанию установлен как Space. Теперь вся строка привязана к %%a
. так что если replacements.txt
содержит
word1=yes
word15=no
того set
выполняются в set "$word1=yes"
(и так далее для остальной части файла)
Наконец, есть на самом деле только один for
цикл и подпрограмма. Конструкция (for...)>filename
отправляет что-нибудь ECHO
ed во время цикла в файл - даже если это echo
ed в подпрограмме. >file
означает сделать новый файл, >>file
будет означать append to an existing file if there is one or make a new one.
Этот заключительный for/f
читает ECH строки из моего тестового файла, q21450455.txt
word1 more words
not here word1
not at all here
word15 even more words
tokenising с использованием разделителей по умолчанию, назначая первый маркер (1) в %%a
и остаток (*) до %%b
. Затем подпрограмма rep1
равна call
ed и передаются два параметра - %%a
в качестве первого (первое слово из строки, вплоть до первого разделителя) и "%%b"
в качестве второго. Весь остаток строки находится в %%b
- но это может содержать разделители, поэтому "quoting it"
сохраняет весь остаток линии вместе как один элемент.
В :rep1
мы видим, определена ли переменная $%1
. % 1 является первым параметром для процедуры, следовательно, первое слово из файла, поэтому оператор будет видеть, существует ли $word1
как переменная среды. Если это так, мы устанавливаем newword
на содержимое $%1
, поэтому нам нужно позвонить set ... = %% $% 1 %%. Это трюк синтаксического анализа и выполняет набор ... =% v $ word1% или что бы ни было первым словом - и это было установлено ранее в среду.
Если $word1
не определен в окружающей среде, то newword
просто устанавливается на первый параметр (то есть первое слово из строки файла).
И, наконец, echo
это новое и %~2
, что означает the second parameter, with any enclosing quotes removed
- и оно перенаправлено к файлу.
Работа выполнена.
Это работает! Спасибо! Но есть некоторые тонкости, которые я хотел бы понять. Что там% 1 во втором FOR? – Guy
@Matthew я обновил свой ответ –
Спасибо :) О, и еще одна вещь. Почему во втором есть «токены = 1, *»? Разве это не было бы так, если бы это было просто «tokens =» * »? – Guy