【问题标题】:Using two files to replace text in another file with bat?使用两个文件用bat替换另一个文件中的文本?
【发布时间】:2015-02-25 01:52:44
【问题描述】:

我在为社区做点事情时遇到了一些困难,我需要帮助。我是 .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 显示您对处理第三个文件的期望。我从您的描述中得知 file1 具有 ID 和名称file2 中的相应行是实际名称,无论该 ID 出现在 file3 中的什么位置,都可以替换为该 ID。对吗?
  • 是的,这是正确的。 ID.txt 和 Name.txt 在确切的行号上有相应的文本。 Data.txt 有一堆 ID 字符串遍布整个区域,我们只需要将这些字符串翻译成名称。
  • 好的,我更改了主帖以符合您要求的标准。

标签: batch-file text replace


【解决方案1】:

如果您的第三个文件只包含 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

【讨论】:

  • 我有大约 500 多对 Id 和名称是的。还需要保留其他原始文本的一部分。
【解决方案2】:
@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的数据将数据文件中的行数扩展到10000多行,并测量了上述过程。在我的机器上花了 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 的解析器没有意义的字符,即。字母表(大写和小写)和数字以及集合[@#$+_-{}:.] 请注意,这非常明确地排除了 SpaceTab 和逗号,而且该批次很少区分案例....

哦 - 运行时,你问?

呃,0.63 秒。

【讨论】:

  • 这正是我需要 Magoo 的解决方案。 .bat 转换它的速度很慢,但它可以创造奇迹。非常感谢!
猜你喜欢
  • 2018-03-29
  • 1970-01-01
  • 2019-03-06
  • 2017-06-01
  • 2012-08-25
  • 1970-01-01
  • 1970-01-01
  • 2016-07-12
  • 2021-09-18
相关资源
最近更新 更多