如何从文本文件中提取某些文本并用该文本替换另一个文件中的关键字?
How to extract certain text from a text file and replace keyword in another file with this text?
长话短说,我有一个 SQL 脚本,当一个动作失败时我会运行它,我有一个日志,里面有我需要的所有信息,我只是替换了这个 SQL 的某些部分脚本与日志文件中的文本。
我的问题:有没有办法从批处理文件中执行此操作?
例子
日志文件包含查询 ID:123456 和 EntityID:654321、23123432、345345435、435435、438980943 等
我有 SQL 脚本,我将 "QueryID" 替换为日志中的查询 ID 号,我还想将 "entityID" 替换为日志中的所有实体 ID文件通常有几百个。
这是 SQL 脚本
select *
from search_results
where search_id = ***query_id***
and entity_id in (select entity_id
from search_results
where search_id = ***query_id***
and entity_id in (***entityID***))
上面是我运行的 SQL 脚本,我想用查询 ID 替换 Query_id从我拥有的日志文件中,然后将 Entity_ID 替换为同一日志文件中的实体 ID
多年来我一直试图找到解决这个问题的方法,但我卡住了] 剧本
@ECHO OFF
for /f "tokens=4 delims=:" %%G in ('TYPE logfile.txt ^|FIND /i "EntityID"') do (
ECHO %%G,>>entity.txt
)
我可以对查询 ID 执行相同的操作,但由于只有一个 ID,我只是将其复制并粘贴进去。
简而言之,我想在 directory/file 中放置一个日志,然后运行一个 Bat 文件来为我生成 SQL 脚本(在文本文件中)。
任何帮助将不胜感激:)
额外信息
我必须运行这个脚本来找出 eshot 中的哪些人,eshot has/hasn 没有被发送到,这样我就可以删除那些已经将 eshot 发送给他们的人并将他们从SQL 中的列表,这样可以再次设置 eshot,人们不会收到很多电子邮件。
QueryID 是列出电子邮件的列表的 ID,entityID 是列表中电子邮件地址的 ID。
所以简而言之,sql 脚本找到电子邮件地址列表(通过 QueryID),然后显示 eshot 已发送到的电子邮件地址(通过日志文件中的实体 ID),这样我就可以删除从列表中删除它们并重新发送 eshot,人们不会收到两封电子邮件。
当人们的电子邮件地址中包含愚蠢的字符时,这通常会失败。
这是我删除了数据敏感信息的日志文件。
> ==========================================================================================
>
> ------------------------------------------------------------------------------------------
> Domain :10007
> User :10725
> Language :1
> Entity :0
> Role :-1
> View :8997749 ()
> Region :8998836 ()
> Control :
> Date/Time :5 janvier 2015 15:49:33 UTC
> ==========================================================================================
> [15:49:33 UTC] TotalQueryIDs :1:
> [15:49:33 UTC] User :10725:
> [15:49:33 UTC] Template :20005406:
> !!! [15:49:33 UTC] queryID :96566:
> [15:49:33 UTC] QueryCount :781:
> [15:49:33 UTC] Count :1:
> !!! [15:49:33 UTC] EntityID :49891:
> [15:49:33 UTC] Contact :49891:
> [15:49:33 UTC] Today :05/01/15:
> [15:49:33 UTC] Time :16:49:
> [15:49:33 UTC] EmailID ::
> [15:49:33 UTC] posOfSign :7:
> [15:49:33 UTC] posOfSign :7:
> [15:49:33 UTC] posOfDot :10:
> [15:49:33 UTC] emailValidity ::
> [15:49:33 UTC] flag ::
> [15:49:33 UTC] Language :English:
> [15:49:33 UTC] Template1 :COBE8:
> [15:49:33 UTC] flag ::
> [15:49:33 UTC] --<*> RSH <*>--
> [15:49:33 UTC] TempName ::
> [15:49:33 UTC] DocCount :96:
> [15:49:33 UTC] BeforeAdd ::
> [15:49:33 UTC] AfterAdd ::
> [15:49:33 UTC] afterIF ::
> [15:49:33 UTC] preview :N:
> [15:49:33 UTC] preview :N:
> [15:49:34 UTC] DocCount :1:
> [15:49:34 UTC] countofATT ::
> [15:49:34 UTC] Today :05/01/15:
> [15:49:34 UTC] Time :16:49:
> [15:49:34 UTC] EMAILSEND ::
> [15:49:34 UTC] preview :N:
> [15:49:34 UTC] Role :111:
> [15:49:34 UTC] e1 ::>
> [15:49:34 UTC] e1 ::
> [15:49:34 UTC] DocCount :96:
> [15:49:34 UTC] DocCount :96:
> [15:49:34 UTC] e1 ::
> [15:49:34 UTC] countofATT ::
> [15:49:34 UTC] DocCount :1:
> [15:49:34 UTC] e1 ::
> [15:49:34 UTC] --<*> About to Save Journal <*>-->
> [15:49:34 UTC] --<*> Journal Saved <*>--
> [15:49:34 UTC] EmailID ::
> [15:49:34 UTC] Count :2:
> !!! [15:49:34 UTC] EntityID :49903:
> [15:49:34 UTC] Contact :49903:
> [15:49:34 UTC] Today :05/01/15:
> [15:49:34 UTC] Time :16:49:
> [15:49:34 UTC] EmailID ::
> [15:49:34 UTC] posOfSign :3:
> [15:49:34 UTC] Eshot :Y:
> [15:49:34 UTC] posOfSign :3:
> [15:49:34 UTC] posOfDot :11:
> [15:49:34 UTC] emailValidity ::
> [15:49:34 UTC] flag ::
> [15:49:34 UTC] Phone ::
> [15:49:34 UTC] Language :English:
> [15:49:34 UTC] Template1 :COBE8:
> [15:49:34 UTC] flag ::
这是 SQL 脚本的示例
select * from search_results where search_id =96566 and
entity_id in (select entity_id from search_results where search_id =96566
And entity_id in(49891,49903,51404,137395,137492,))
谢谢大家的帮助,真的很感激。
更新
我使用了以下内容(感谢@Keeghan McGarry)并得到了我想要的,但是实体 ID 只显示列表中的最后一个,有没有办法让所有实体 ID 都显示出来,
供参考
日志调用bo.txt,脚本转到sql.txt
@ECHO OFF
FOR /F "tokens=4 delims=:" %%e IN ('TYPE bo.txt ^|FIND /i "EntityID"') DO SET entity=%%e
FOR /F "tokens=4 delims=:" %%q IN ('TYPE bo.txt ^|FIND /i "queryID"') DO SET query=%%q
ECHO select * from search_results where search_id =%query% and entity_id in >> sql.txt
ECHO (select entity_id from search_results where search_id =%query%>> sql.txt
ECHO And entity_id in>> sql.txt
ECHO (%entity%))>> sql.txt
上面给出了下面这个但应该有这些实体 ID 的 49891,49903,51404,137395,137492,
select * from search_results where search_id =96566 and entity_id in
(select entity_id from search_results where search_id =96566 And
entity_id in (137492))
非常感谢所有帮助。
我的建议是为您的 EntityID 和 QueryID 设置一个变量,而不是输出到单独的文件。这样你就可以将整个 SQL 脚本回显到文件中,并在需要的地方添加变量。一个非常简短的例子(未经测试,因为我没有你的LogFile.txt):
@ECHO OFF
FOR /F "tokens=4 delims=:" %%F IN ('TYPE logfile.txt ^|FIND /i "EntityID"') DO SET SET entity=%%F
FOR /F "***Need to set these***" %%G IN ('TYPE logfile.txt ^|FIND /i "query_ID"') DO SET SET query=%%G
ECHO select * from search_results where search_id = %query% and entity_id in > query.txt
ECHO (select entity_id from search_results where search_id = %query% >> query.txt
ECHO And entity_id in >> query.txt
ECHO (%entity%)) >> query.txt
您只需为查询 ID 输入正确的标记和分隔符,然后它就可以工作了。如果您可以提供示例 LogFile.txt 那么我可以 test/expand 这段代码。
希望这对您有所帮助
编辑
根据编辑后的问题,要获取每个 entityID,请将查询输出放在 FOR 循环中。
@ECHO OFF
setlocal enabledelayedexpansion
FOR /F "tokens=4 delims=:" %%q IN ('TYPE bo.txt ^|FIND /i "queryID"') DO SET query=%%q
FOR /F "tokens=4 delims=:" %%e IN ('TYPE bo.txt ^|FIND /i "EntityID"') DO (
SET entity=%%e
ECHO select * from search_results where search_id =%query% and entity_id in >> sql.txt
ECHO (select entity_id from search_results where search_id =%query%>> sql.txt
ECHO And entity_id in>> sql.txt
ECHO (!entity!^)^)>> sql.txt
ECHO.>> sql.txt
)
如您所见,我调换了 FOR 循环的顺序,queryID 现在先进行,sql.txt 的输出在另一个循环内,因此它会在每次找到 entityID 时输出它。添加的 ECHO.>> sql.txt
是为了分解 sql.txt 中的每个查询。
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "destdir=U:\destdir"
SET "queryid="
FOR /f "tokens=4,5 delims=[]:" %%a IN (
'type q27849431.txt^|findstr /i /l /c:" queryID " /c:" EntityID "'
) DO (
IF "%%a"==" queryID " CALL :generate %%b
IF "%%a"==" EntityID " SET "entityids=!entityids!,%%b"
)
)
CALL :generate 0
GOTO :EOF
:generate
IF NOT DEFINED queryid GOTO first
SET "entityids=%entityids: =%"
(
ECHO select * from search_results where search_id = %queryid% and entity_id in
ECHO (select entity_id from search_results where search_id = %queryid%
ECHO And entity_id in
ECHO (%entityids:~1%^)^)^)
)>"%destdir%\query%queryid%.sql"
:first
SET /a queryid=%1
SET "entityids="
GOTO :eof
嗯 - 提供了一些数据。我相信日志行实际开始 >Spaces 并且目标行包含 !!!
的可能性极小,所以我从中删除了那些数据并将结果放在名为 q27849431.txt
的文件中供我测试。
我还假设有一个要处理的日志文件(q27849431.txt
)并且它的结构是
[15:49:33 UTC] TotalQueryIDs :1:
[15:49:33 UTC] queryID :96577:
[15:49:33 UTC] EntityID :49891:
[15:49:34 UTC] EntityID :49903:
[15:49:33 UTC] TotalQueryIDs :1:
[15:49:33 UTC] queryID :96588:
[15:49:33 UTC] EntityID :49896:
[15:49:34 UTC] EntityID :49943:
[15:49:34 UTC] posOfSign :3:
(显示重要和随机行 - 特别是包含重要字符串 queryid
的行,不分大小写)
从那里开始,批处理是 VB- 程序员的工作。找到 queryid
然后构建一个 entityids
的字符串。每次 queryid
更改时输出一个新的查询,一个在日志文件末尾的运气(因为不会有进一步的 queryids 但一个仍然累积但不输出)
每个 sql 都生成到其自己的文件中,并具有明显的名称。如果你想把它们都放在同一个文件中,那么将 >"%destdir%\query%queryid%.sql"
更改为 >>"whateverdestinationfilenameyouwant"
但该构造将 append 到任何现有的 "whateverdestinationfilenameyouwant"
所以它可能是在脚本开头删除 "whateverdestinationfilenameyouwant"
的想法。
在大家的帮助下,特别是@magoo,我终于得到了答案:)
@ECHO OFF
setlocal enabledelayedexpansion
FOR /F "tokens=4 delims=:" %%q IN ('TYPE bo.txt ^|FIND /i "queryID"') DO (SET query=%%q)
ECHO select * from search_results where search_id =%query% and entity_id in >> sql.txt
ECHO (select entity_id from search_results where search_id =%query%>> sql.txt
ECHO And entity_id in(>> sql.txt
FOR /F "tokens=4 delims=:" %%e IN ('TYPE bo.txt ^|FIND /i "EntityID"') DO (SET entity=%%e
ECHO !entity!>> sql.txt)
echo )) >>sql.txt
以上脚本生成以下 SQL 脚本:
select * from search_results where search_id =96566 and entity_id in
(select entity_id from search_results where search_id =96566
And entity_id in(
49891
49903
51404
137395
137492
))
来自问题中的日志文件。
我将添加一行来查找和删除 sql.txt(如果它在 运行 脚本的其余部分之前已经存在),这样就不会在同一个脚本中包含很多 SQL 脚本文件。
感谢大家的帮助
长话短说,我有一个 SQL 脚本,当一个动作失败时我会运行它,我有一个日志,里面有我需要的所有信息,我只是替换了这个 SQL 的某些部分脚本与日志文件中的文本。
我的问题:有没有办法从批处理文件中执行此操作?
例子
日志文件包含查询 ID:123456 和 EntityID:654321、23123432、345345435、435435、438980943 等
我有 SQL 脚本,我将 "QueryID" 替换为日志中的查询 ID 号,我还想将 "entityID" 替换为日志中的所有实体 ID文件通常有几百个。
这是 SQL 脚本
select *
from search_results
where search_id = ***query_id***
and entity_id in (select entity_id
from search_results
where search_id = ***query_id***
and entity_id in (***entityID***))
上面是我运行的 SQL 脚本,我想用查询 ID 替换 Query_id从我拥有的日志文件中,然后将 Entity_ID 替换为同一日志文件中的实体 ID
多年来我一直试图找到解决这个问题的方法,但我卡住了] 剧本
@ECHO OFF
for /f "tokens=4 delims=:" %%G in ('TYPE logfile.txt ^|FIND /i "EntityID"') do (
ECHO %%G,>>entity.txt
)
我可以对查询 ID 执行相同的操作,但由于只有一个 ID,我只是将其复制并粘贴进去。
简而言之,我想在 directory/file 中放置一个日志,然后运行一个 Bat 文件来为我生成 SQL 脚本(在文本文件中)。
任何帮助将不胜感激:)
额外信息
我必须运行这个脚本来找出 eshot 中的哪些人,eshot has/hasn 没有被发送到,这样我就可以删除那些已经将 eshot 发送给他们的人并将他们从SQL 中的列表,这样可以再次设置 eshot,人们不会收到很多电子邮件。
QueryID 是列出电子邮件的列表的 ID,entityID 是列表中电子邮件地址的 ID。
所以简而言之,sql 脚本找到电子邮件地址列表(通过 QueryID),然后显示 eshot 已发送到的电子邮件地址(通过日志文件中的实体 ID),这样我就可以删除从列表中删除它们并重新发送 eshot,人们不会收到两封电子邮件。
当人们的电子邮件地址中包含愚蠢的字符时,这通常会失败。
这是我删除了数据敏感信息的日志文件。
> ==========================================================================================
>
> ------------------------------------------------------------------------------------------
> Domain :10007
> User :10725
> Language :1
> Entity :0
> Role :-1
> View :8997749 ()
> Region :8998836 ()
> Control :
> Date/Time :5 janvier 2015 15:49:33 UTC
> ==========================================================================================
> [15:49:33 UTC] TotalQueryIDs :1:
> [15:49:33 UTC] User :10725:
> [15:49:33 UTC] Template :20005406:
> !!! [15:49:33 UTC] queryID :96566:
> [15:49:33 UTC] QueryCount :781:
> [15:49:33 UTC] Count :1:
> !!! [15:49:33 UTC] EntityID :49891:
> [15:49:33 UTC] Contact :49891:
> [15:49:33 UTC] Today :05/01/15:
> [15:49:33 UTC] Time :16:49:
> [15:49:33 UTC] EmailID ::
> [15:49:33 UTC] posOfSign :7:
> [15:49:33 UTC] posOfSign :7:
> [15:49:33 UTC] posOfDot :10:
> [15:49:33 UTC] emailValidity ::
> [15:49:33 UTC] flag ::
> [15:49:33 UTC] Language :English:
> [15:49:33 UTC] Template1 :COBE8:
> [15:49:33 UTC] flag ::
> [15:49:33 UTC] --<*> RSH <*>--
> [15:49:33 UTC] TempName ::
> [15:49:33 UTC] DocCount :96:
> [15:49:33 UTC] BeforeAdd ::
> [15:49:33 UTC] AfterAdd ::
> [15:49:33 UTC] afterIF ::
> [15:49:33 UTC] preview :N:
> [15:49:33 UTC] preview :N:
> [15:49:34 UTC] DocCount :1:
> [15:49:34 UTC] countofATT ::
> [15:49:34 UTC] Today :05/01/15:
> [15:49:34 UTC] Time :16:49:
> [15:49:34 UTC] EMAILSEND ::
> [15:49:34 UTC] preview :N:
> [15:49:34 UTC] Role :111:
> [15:49:34 UTC] e1 ::>
> [15:49:34 UTC] e1 ::
> [15:49:34 UTC] DocCount :96:
> [15:49:34 UTC] DocCount :96:
> [15:49:34 UTC] e1 ::
> [15:49:34 UTC] countofATT ::
> [15:49:34 UTC] DocCount :1:
> [15:49:34 UTC] e1 ::
> [15:49:34 UTC] --<*> About to Save Journal <*>-->
> [15:49:34 UTC] --<*> Journal Saved <*>--
> [15:49:34 UTC] EmailID ::
> [15:49:34 UTC] Count :2:
> !!! [15:49:34 UTC] EntityID :49903:
> [15:49:34 UTC] Contact :49903:
> [15:49:34 UTC] Today :05/01/15:
> [15:49:34 UTC] Time :16:49:
> [15:49:34 UTC] EmailID ::
> [15:49:34 UTC] posOfSign :3:
> [15:49:34 UTC] Eshot :Y:
> [15:49:34 UTC] posOfSign :3:
> [15:49:34 UTC] posOfDot :11:
> [15:49:34 UTC] emailValidity ::
> [15:49:34 UTC] flag ::
> [15:49:34 UTC] Phone ::
> [15:49:34 UTC] Language :English:
> [15:49:34 UTC] Template1 :COBE8:
> [15:49:34 UTC] flag ::
这是 SQL 脚本的示例
select * from search_results where search_id =96566 and
entity_id in (select entity_id from search_results where search_id =96566
And entity_id in(49891,49903,51404,137395,137492,))
谢谢大家的帮助,真的很感激。
更新
我使用了以下内容(感谢@Keeghan McGarry)并得到了我想要的,但是实体 ID 只显示列表中的最后一个,有没有办法让所有实体 ID 都显示出来, 供参考 日志调用bo.txt,脚本转到sql.txt
@ECHO OFF
FOR /F "tokens=4 delims=:" %%e IN ('TYPE bo.txt ^|FIND /i "EntityID"') DO SET entity=%%e
FOR /F "tokens=4 delims=:" %%q IN ('TYPE bo.txt ^|FIND /i "queryID"') DO SET query=%%q
ECHO select * from search_results where search_id =%query% and entity_id in >> sql.txt
ECHO (select entity_id from search_results where search_id =%query%>> sql.txt
ECHO And entity_id in>> sql.txt
ECHO (%entity%))>> sql.txt
上面给出了下面这个但应该有这些实体 ID 的 49891,49903,51404,137395,137492,
select * from search_results where search_id =96566 and entity_id in (select entity_id from search_results where search_id =96566 And entity_id in (137492))
非常感谢所有帮助。
我的建议是为您的 EntityID 和 QueryID 设置一个变量,而不是输出到单独的文件。这样你就可以将整个 SQL 脚本回显到文件中,并在需要的地方添加变量。一个非常简短的例子(未经测试,因为我没有你的LogFile.txt):
@ECHO OFF
FOR /F "tokens=4 delims=:" %%F IN ('TYPE logfile.txt ^|FIND /i "EntityID"') DO SET SET entity=%%F
FOR /F "***Need to set these***" %%G IN ('TYPE logfile.txt ^|FIND /i "query_ID"') DO SET SET query=%%G
ECHO select * from search_results where search_id = %query% and entity_id in > query.txt
ECHO (select entity_id from search_results where search_id = %query% >> query.txt
ECHO And entity_id in >> query.txt
ECHO (%entity%)) >> query.txt
您只需为查询 ID 输入正确的标记和分隔符,然后它就可以工作了。如果您可以提供示例 LogFile.txt 那么我可以 test/expand 这段代码。
希望这对您有所帮助
编辑
根据编辑后的问题,要获取每个 entityID,请将查询输出放在 FOR 循环中。
@ECHO OFF
setlocal enabledelayedexpansion
FOR /F "tokens=4 delims=:" %%q IN ('TYPE bo.txt ^|FIND /i "queryID"') DO SET query=%%q
FOR /F "tokens=4 delims=:" %%e IN ('TYPE bo.txt ^|FIND /i "EntityID"') DO (
SET entity=%%e
ECHO select * from search_results where search_id =%query% and entity_id in >> sql.txt
ECHO (select entity_id from search_results where search_id =%query%>> sql.txt
ECHO And entity_id in>> sql.txt
ECHO (!entity!^)^)>> sql.txt
ECHO.>> sql.txt
)
如您所见,我调换了 FOR 循环的顺序,queryID 现在先进行,sql.txt 的输出在另一个循环内,因此它会在每次找到 entityID 时输出它。添加的 ECHO.>> sql.txt
是为了分解 sql.txt 中的每个查询。
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "destdir=U:\destdir"
SET "queryid="
FOR /f "tokens=4,5 delims=[]:" %%a IN (
'type q27849431.txt^|findstr /i /l /c:" queryID " /c:" EntityID "'
) DO (
IF "%%a"==" queryID " CALL :generate %%b
IF "%%a"==" EntityID " SET "entityids=!entityids!,%%b"
)
)
CALL :generate 0
GOTO :EOF
:generate
IF NOT DEFINED queryid GOTO first
SET "entityids=%entityids: =%"
(
ECHO select * from search_results where search_id = %queryid% and entity_id in
ECHO (select entity_id from search_results where search_id = %queryid%
ECHO And entity_id in
ECHO (%entityids:~1%^)^)^)
)>"%destdir%\query%queryid%.sql"
:first
SET /a queryid=%1
SET "entityids="
GOTO :eof
嗯 - 提供了一些数据。我相信日志行实际开始 >Spaces 并且目标行包含 !!!
的可能性极小,所以我从中删除了那些数据并将结果放在名为 q27849431.txt
的文件中供我测试。
我还假设有一个要处理的日志文件(q27849431.txt
)并且它的结构是
[15:49:33 UTC] TotalQueryIDs :1:
[15:49:33 UTC] queryID :96577:
[15:49:33 UTC] EntityID :49891:
[15:49:34 UTC] EntityID :49903:
[15:49:33 UTC] TotalQueryIDs :1:
[15:49:33 UTC] queryID :96588:
[15:49:33 UTC] EntityID :49896:
[15:49:34 UTC] EntityID :49943:
[15:49:34 UTC] posOfSign :3:
(显示重要和随机行 - 特别是包含重要字符串 queryid
的行,不分大小写)
从那里开始,批处理是 VB- 程序员的工作。找到 queryid
然后构建一个 entityids
的字符串。每次 queryid
更改时输出一个新的查询,一个在日志文件末尾的运气(因为不会有进一步的 queryids 但一个仍然累积但不输出)
每个 sql 都生成到其自己的文件中,并具有明显的名称。如果你想把它们都放在同一个文件中,那么将 >"%destdir%\query%queryid%.sql"
更改为 >>"whateverdestinationfilenameyouwant"
但该构造将 append 到任何现有的 "whateverdestinationfilenameyouwant"
所以它可能是在脚本开头删除 "whateverdestinationfilenameyouwant"
的想法。
在大家的帮助下,特别是@magoo,我终于得到了答案:)
@ECHO OFF
setlocal enabledelayedexpansion
FOR /F "tokens=4 delims=:" %%q IN ('TYPE bo.txt ^|FIND /i "queryID"') DO (SET query=%%q)
ECHO select * from search_results where search_id =%query% and entity_id in >> sql.txt
ECHO (select entity_id from search_results where search_id =%query%>> sql.txt
ECHO And entity_id in(>> sql.txt
FOR /F "tokens=4 delims=:" %%e IN ('TYPE bo.txt ^|FIND /i "EntityID"') DO (SET entity=%%e
ECHO !entity!>> sql.txt)
echo )) >>sql.txt
以上脚本生成以下 SQL 脚本:
select * from search_results where search_id =96566 and entity_id in
(select entity_id from search_results where search_id =96566
And entity_id in(
49891
49903
51404
137395
137492
))
来自问题中的日志文件。
我将添加一行来查找和删除 sql.txt(如果它在 运行 脚本的其余部分之前已经存在),这样就不会在同一个脚本中包含很多 SQL 脚本文件。
感谢大家的帮助