使用两个文件用bat替换另一个文件中的文本?

时间:2014-12-28 18:31:32

标签: batch-file text replace

我有点想要为社区做点什么,我正在花时间和我需要帮助。我是.bat和所有的新人。

我有3个文件。

1)包含ID列表的文件 2)具有ID的专有名称列表的文件 3)一个包含大量文本的文件,其中包含随机ID。

我想使用ID和名称来替换第三个文件中的ID。第一个和第二个文件看起来像:

ID.txt
======
001_Blue019
002_Bluer11
003_Buster142

Name.txt
======
Bob Blue
Bluer Baxster
Buster Arnold

一切都完全符合它的正确路线。我想使用这两个文件来更改包含随机放置在文本文件中的ID的第三个文件,某些ID可能会出现多次。我遇到了麻烦,我该如何做到这一点?

第三个文件看起来像这样,但有超过500个不同的ID出现不止一次:

001_Blue019
001_Blue019
001_Blue019
002_Bluer11
001_Blue019
001_Blue019
003_Buster142

最终输出或更改应如下所示

Bob Blue
Bob Blue
Bob Blue
Bluer Baxster
Bob Blue
Bob Blue
Buster Arnold

2 个答案:

答案 0 :(得分:0)

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: remove variables starting $ or #
For %%b IN ($ #) DO FOR  /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
:: load $*=IDs, #*=names
SET /a count=0
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r ".*" q27679364u.txt') DO SET "$%%a=%%b"
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r ".*" q27679364n.txt') DO SET "#%%a=%%b"&SET /a count+=1
(
FOR /f "delims=" %%a IN (q27679364d.txt) DO (
 SET "line=%%a"
 CALL :process
)
)>"newfile.txt"

GOTO :EOF

:process
FOR /l %%i IN (1,1,%count%) DO CALL :SUBST "%%$%%i%%" "%%#%%i%%"
ECHO(%line%
GOTO :eof

:SUBST
CALL SET "line=%%line:%~1=%~2%%
GOTO :eof

我使用名为q27679364u.txt的文件包含您的ID数据,并使用q27679364n.txt您的名称数据进行测试。

制作newfile.txt

将此输入数据放在文件q27679364d.txt中:

substitute here: 001_Blue019
nothing to substitute
what about this? 002_Bluer11 and 003_Buster142 and 001_Blue019
--- now your data ----
001_Blue019
001_Blue019
001_Blue019
002_Bluer11
001_Blue019
001_Blue019
003_Buster142

(我在等待时编写了自己的数据文件;然后在最后添加了数据)

结果是:

substitute here: Bob Blue
nothing to substitute
what about this? Bluer Baxster and Buster Arnold and Bob Blue
--- now your data ----
Bob Blue
Bob Blue
Bob Blue
Bluer Baxster
Bob Blue
Bob Blue
Buster Arnold

出现在newfile.txt


附录

批次的速度并不清楚,但可以通过调整例程来完成大量工作,特别是考虑到正在处理的数据的特性。

通过OP数据的质量复制,我将数据文件中的行数扩展到10,000多个,并测量了上述过程。在我的机器上花了176秒(实际时间取决于机器特性和每个文件的大小。)

然后我修改了例程,假设第三个文件中的数据包含来自ID文件的行,按随机顺序并且可能重复。

结果:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: remove variables starting $ or #
For %%b IN ($ #) DO FOR  /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
:: load $*=IDs, #*=names
SET /a count=0
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r ".*" q27679364u.txt') DO SET "$%%a=%%b"
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r ".*" q27679364n.txt') DO SET "#%%a=%%b"&SET /a count+=1
(
FOR /f "delims=" %%a IN (q27679364d.txt) DO (
 FOR /f "tokens=1*delims=$=" %%i IN ('set $') DO IF /i "%%j"=="%%a" ECHO !#%%i!
)
)>"newfile.txt"
GOTO :EOF

在109秒内跑了 - 这是一个有用的节省。

所以我想得更远。使用相同的数据,我开发了这个:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: remove variables starting $ or # or _
For %%b IN ($ # _) DO FOR  /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
:: load $*=IDs, #*=names
SET /a count=0
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r ".*" q27679364u.txt') DO SET "$%%a=%%b"
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r ".*" q27679364n.txt') DO SET "#%%a=%%b"&SET /a count+=1
FOR /L %%a IN (1,1,%count%) DO SET "_!$%%a!=!#%%a!"&SET "$%%a="&SET "#%%a="
(
FOR /f "delims=" %%a IN (q27679364d.txt) DO (ECHO !_%%a!
)
)>"newfile.txt"
GOTO :EOF

相同的结果文件,它假定ID和名称都是由“漂亮的字符”构成的 - 那些对CMD的解析器没有意义的那些字符。字母表(大写和小写)和数字以及集[@#$+_-{}:.]注意这非常明确地排除了空间 Tab 和逗号,而且该批次很少关于案件的区别......

哦 - 运行时间,你问?

呃,0.63秒。

答案 1 :(得分:0)

如果您的第3个文件只包含ID,如示例所示,那么以下批处理脚本应该非常快:

@echo off
setlocal enableDelayedExpansion

:: Load the list of IDs
set "find="
<name.txt ( for /f "usebackq delims=" %%A in ("id.txt") do (
  set "name="
  set /p "name="
  set "_%%A=!name!"
))

for /f "usebackq delims=" %%A in ("test.txt") do echo(!_%%A!

如果第三个文件中的ID与其他文本混合在一起,那么我有一个不同的快速解决方案,只要您拥有不超过四或五百个ID /名称对,它就能正常工作。它使用JREPL.BAT - 一个混合的JScript /批处理脚本,可以在XP以后的任何Windows机器上本机运行。

@echo off
setlocal enableDelayedExpansion

:: Load the list of IDs
set "find="
for /f "usebackq delims=" %%A in ("id.txt")   do set "find=!find!|%%A"
set find

:: Load the list of Names
set "repl="
for /f "usebackq delims=" %%A in ("name.txt") do set "repl=!repl!|%%A"
set repl

:: Substitute Names for all IDs within test.txt and write the result to out.txt
call jrepl find repl /l /t "|" /v /f test.txt /o out.txt