我怎样才能制作一个批处理文件来告诉我文本文件的哪些行不在另一个文件中?
How can I make a batch file that will tell me which lines of a text file are NOT in another file?
我想做的是获取一个文本文件,其中包含要搜索的一堆字符串,每个字符串都在其自己的行中,然后在文件中搜索这些字符串中的每一个 (check.txt) .我希望输出是一个文本文件,其中包含无法找到的所有字符串的列表。
到目前为止,我已经尝试了一些事情。
for /F "tokens=*" %%A in search.txt do (
@echo on
FINDSTR %%A check.txt
IF ERRORLEVEL 1 echo %%A FAIL > fail_match.txt
)
我的另一个尝试(这次只是想告诉我整个列表好不好)是
@echo on
FINDSTR /g:search.txt check.txt > a_match.txt
IF ERRORLEVEL 1 echo bad > a_match.txt
我知道这些都是非常基础的,而且我确信有一些我只是不明白的简单答案。我不是程序员;我只是想让我的工作更轻松(更快)。
澄清一下,我要搜索的内容列表在 search.txt 中,我要检查的内容列表是 check.txt。 Check.txt 是一个 json 文件,所以它是一个巨大的行。我不知道这是否会有所作为。我想要 search.txt 中不在 check.txt.
中的所有行的列表
如果我没看错你的问题(输出 check.txt 中不在 search.txt 中的所有行),这一行应该做:
findstr /v /x /g:search.txt check.txt > nomatch.txt
您的搜索方案在两个方面似乎很幼稚:
1) JSON不保证是单行。有效的 JASON 可以有任意数量的空格,包括换行符。如果您的搜索字符串在多行中逻辑匹配,这可能会导致问题。
2) 子串匹配呢?假设一个搜索字符串是 bat
,而您的 JSON 包含 bath
。我怀疑你会认为这是一场比赛。
对于您的情况,上述问题可能都不是问题。假设它们不是,那么可能有一个使用 FINDSTR 的相当简单的解决方案。
除了
,您第一次尝试就接近成功了
A) - 您的 FOR /F IN()
子句缺少括号
B) - 您想强制将每个搜索字符串解释为字符串文字,可能带有空格。这需要 /C:
选项。
C) - 您假设前导空格在您的搜索字符串中并不重要("tokens=*"
去除前导空格)
D) - 您假设没有搜索行以分号开头。 (默认EOF字符为分号,FOR /F跳过所有以EOF字符开头的行)
E) - 引号和反斜杠必须在搜索字符串中转义:
\" -> \\\"
、\ -> \
、" -> \"
。有关详细信息,请参阅 What are the undocumented features and limitations of the Windows FINDSTR command?。
点 C) 和 D) 可以通过使用以下奇怪的语法禁用 EOF 和 DELIMS 来修复:
for delims^=^ eof^= %%A in ...
点 E) 可以通过定义变量并通过搜索和替换添加转义序列来解决。但这需要延迟扩展,但延迟扩展会在扩展时破坏 FOR /F 变量,如果它们包含 !
。因此延迟扩展必须在循环中有策略地打开和关闭。
您可以使用条件命令串联 ||
而不是使用 IF ERRORLEVEN n
,以便在上一个命令失败时采取措施。
您不需要查看 FINDSTR 命令的输出,因此可以将其重定向到 NUL。
您可以通过在循环外仅重定向一次来提高性能。
@echo off
setlocal disableDelayedExpansion
>fail_match.txt (
for /f delims^=^ eol^= %%A in (search.txt) do (
set "search=%%A"
setlocal enableDelayedExpansion
set "search2=!search:\"=\"!"
set "search2=!search2:\=\!"
set "search2=!search2:"=\"!"
findstr /c:"!search2!" check.txt >nul || echo !search!
endlocal
)
)
如果 none 个搜索字符串以 ;
开头,并且没有搜索字符串包含 "
或 \
,那么解决方案可以很简单:
@echo off
setlocal disableDelayedExpansion
>fail_match.txt (
for /f "delims=" %%A in (search.txt) do findstr /c:"%%A" check.txt >nul || echo %%A
)
我想做的是获取一个文本文件,其中包含要搜索的一堆字符串,每个字符串都在其自己的行中,然后在文件中搜索这些字符串中的每一个 (check.txt) .我希望输出是一个文本文件,其中包含无法找到的所有字符串的列表。 到目前为止,我已经尝试了一些事情。
for /F "tokens=*" %%A in search.txt do (
@echo on
FINDSTR %%A check.txt
IF ERRORLEVEL 1 echo %%A FAIL > fail_match.txt
)
我的另一个尝试(这次只是想告诉我整个列表好不好)是
@echo on
FINDSTR /g:search.txt check.txt > a_match.txt
IF ERRORLEVEL 1 echo bad > a_match.txt
我知道这些都是非常基础的,而且我确信有一些我只是不明白的简单答案。我不是程序员;我只是想让我的工作更轻松(更快)。
澄清一下,我要搜索的内容列表在 search.txt 中,我要检查的内容列表是 check.txt。 Check.txt 是一个 json 文件,所以它是一个巨大的行。我不知道这是否会有所作为。我想要 search.txt 中不在 check.txt.
中的所有行的列表如果我没看错你的问题(输出 check.txt 中不在 search.txt 中的所有行),这一行应该做:
findstr /v /x /g:search.txt check.txt > nomatch.txt
您的搜索方案在两个方面似乎很幼稚:
1) JSON不保证是单行。有效的 JASON 可以有任意数量的空格,包括换行符。如果您的搜索字符串在多行中逻辑匹配,这可能会导致问题。
2) 子串匹配呢?假设一个搜索字符串是 bat
,而您的 JSON 包含 bath
。我怀疑你会认为这是一场比赛。
对于您的情况,上述问题可能都不是问题。假设它们不是,那么可能有一个使用 FINDSTR 的相当简单的解决方案。
除了
,您第一次尝试就接近成功了A) - 您的 FOR /F IN()
子句缺少括号
B) - 您想强制将每个搜索字符串解释为字符串文字,可能带有空格。这需要 /C:
选项。
C) - 您假设前导空格在您的搜索字符串中并不重要("tokens=*"
去除前导空格)
D) - 您假设没有搜索行以分号开头。 (默认EOF字符为分号,FOR /F跳过所有以EOF字符开头的行)
E) - 引号和反斜杠必须在搜索字符串中转义:
\" -> \\\"
、\ -> \
、" -> \"
。有关详细信息,请参阅 What are the undocumented features and limitations of the Windows FINDSTR command?。
点 C) 和 D) 可以通过使用以下奇怪的语法禁用 EOF 和 DELIMS 来修复:
for delims^=^ eof^= %%A in ...
点 E) 可以通过定义变量并通过搜索和替换添加转义序列来解决。但这需要延迟扩展,但延迟扩展会在扩展时破坏 FOR /F 变量,如果它们包含 !
。因此延迟扩展必须在循环中有策略地打开和关闭。
您可以使用条件命令串联 ||
而不是使用 IF ERRORLEVEN n
,以便在上一个命令失败时采取措施。
您不需要查看 FINDSTR 命令的输出,因此可以将其重定向到 NUL。
您可以通过在循环外仅重定向一次来提高性能。
@echo off
setlocal disableDelayedExpansion
>fail_match.txt (
for /f delims^=^ eol^= %%A in (search.txt) do (
set "search=%%A"
setlocal enableDelayedExpansion
set "search2=!search:\"=\"!"
set "search2=!search2:\=\!"
set "search2=!search2:"=\"!"
findstr /c:"!search2!" check.txt >nul || echo !search!
endlocal
)
)
如果 none 个搜索字符串以 ;
开头,并且没有搜索字符串包含 "
或 \
,那么解决方案可以很简单:
@echo off
setlocal disableDelayedExpansion
>fail_match.txt (
for /f "delims=" %%A in (search.txt) do findstr /c:"%%A" check.txt >nul || echo %%A
)