@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线,使得每个[系列] =
字符(字符[组] bewteen的delims=
和"
)是一个“令牌分隔符” 。令牌1应用于元变量(在这种情况下为%%a
)。可以提出一系列令牌,然后将其应用于后续的元变量。
所以,$alreadyset=previousvalue
被标记化到$alreadyset
和previousvalue
和$alreadyset
分配给%%a
; set
命令将%%a
设置为空字符串,因此$alreadyset
被设置为空字符串并因此从环境中删除。
set "var=value"
语法用于确保行中的任何尾随空格都包含在分配的值中的而不是。空间是有点难以看到...
下FOR /F
不使用分隔符(=
和"
之间没有字符)将覆盖默认的分隔符设置像空间。整行现在被分配到%%a
。因此,如果replacements.txt
包含
word1=yes
word15=no
那么set
作为set "$word1=yes"
执行(等对文件的其余部分)
最后,真的只是一个for
循环和子程序。 (for...)>filename
构造将循环期间编辑的任何内容发送到文件中 - 即使它在子例程中编辑了echo
也是如此。 >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 %%。这是一个解析技巧,并且执行set ... =%v $ word1%,或者第一个词是什么 - 并且是早期设置到环境中的。
如果在环境中未定义$word1
,则简单地将newword
设置为第一个参数(即文件行中的第一个字)。
最后,我们echo
的新词和%~2
这意味着the second parameter, with any enclosing quotes removed
- 这是重定向到文件。
工作完成。
它的工作原理!谢谢!但我想了解一些行话。在第二个FOR中有什么%1? – Guy
@Matthew我已经更新了我的答案 –
谢谢:)哦,还有一件事。为什么在第二个“令牌= 1,*”?如果它只是“tokens =”*“,那么它会不一样吗? – Guy