首先,我从未真正使用过批次,但我正在努力完成某些事情并开始感到不知所措。 我在Subdirectories中有一堆* txt文件。我想搜索这些* txt文件,如果它们不包含某个字符串(ABCDEF)并将结果输出到新文件中。
如果文件 不包含ABCDEF:
输出Filepath和Name以及以“[”开头的每一行的内容。
如果文件包含ABCDEF一次或多次:
如果未找到,则以“[”开头的行搜索输出以“[”开头的两行中的第一行并在整个文件中移动。
实施例
我的文件如下:
[ID1]
文字不包含abcdef
[ID2]
包含abcdef的文本
[ID3]
文字不包含abcdef此处我的示例输出应为:
文件名
[ID1]
[ID3]
要求的其他说明
我在不同的文件夹中有一堆AD用户组日志。它们随机导出并保存为* .txt。这些文件只包含几行到几百行,并且都以相同的方式设置(如上所示)。
我对伪代码的看法是:
Loop through all folders and subfolders
Go through the files file by file
var output
var searchString = abcdef
var currentfile = Current File Name/Path
While nextline != End of File{
If currentline[0] = "["
output = currentline
While nextline[0] != "["
If currentline.contains(searchString)
If currentfile != 0{
echo currentfile
}
echo output
currentfile = 0
break
else
continue
}
如此相当:寻找searchstring,如果你发现:输出最后一行,然后以“[”开头,然后继续寻找
要添加到目前为止我已经获得的内容:我设法获取包含名称的文件并获取第一个GUID,因为它始终是第一行。
Sadly / v不起作用,因为as一行不包含它评估为true的searchstring。
编辑我得到了它,因为我现在可以通过替换&&来获取所有不包含我的搜索字符串的文件与||。 现在,如果我输出所有以#开头的那些文件,我就在那里完成。
现在,我必须找到一种方法来搜索以“[”开头的行之间的块,如果没有找到则返回值。也许有人有小费? ^^
到目前为止,这是我的代码:
@echo off & setlocal
set "SrcDir=my root directory"
set "FileType=txt"
set "SearchKey=abcdef"
set "LogFile=output.log"
set linenum=1
(for /R %%f in ("*.%FileType%") do (
type "%%~f" | findstr /c:"%SearchKey%" > NUL || (
echo %%~f & for /f "delims=" %%a in ('findstr /r /b /c:"\[" "%%~f"') do echo %%a
)
)) > "%LogFile%"
答案 0 :(得分:0)
可以使用"标记"
完成@echo off
setlocal EnableDelayedExpansion
set searchkey=abcdef
set flag=1
for /r %%f in (*.txt) do (
echo %%f
set "key="
for /f "usebackq delims=" %%a in ("%%f") do (
echo %%a|find "[" >nul && (
if not defined flag if defined key echo !key!
set "key=%%a"
set "flag="
)
echo %%a|find "%searchkey%" >nul && set flag=1
)
if not defined flag if defined key echo !key!
)
key
会记住上一个[something]
行
对于&&
和||
内容,请参阅SS64
对于!variable!
语法,请参阅delayed expansion
答案 1 :(得分:0)
忽略外部FOR循环,除了FINDSTR :)之外,这可以非常有效地完成!
关键是一个鲜为人知的FINDSTR功能来搜索换行符(它的功能有点像正则表达式前瞻)。我在What are the undocumented features and limitations of the Windows FINDSTR command?的答案底部描述了该功能。
@echo off
setlocal
set "SrcDir=my root directory"
set "FileType=txt"
set "SearchKey=abcdef"
set "LogFile=output.log"
(set LF=^
%=This creates a linefeed character=%
)
(
for /r "%SrcDir%" %%F in ("*.%FileType%") do (
echo %%~fF
cmd /v:on /c findstr /rvc:"!LF!.*%SearchKey%" "%%F"|findstr /b "["
echo(
)
) >"%LogFile%"
我分两步解决问题。第一个FINDSTR返回所有不在包含搜索关键字的行之前的行。该结果通过管道输入第二个FINDSTR,仅返回以[
开头的行。
管道的每一侧都在新的cmd.exe进程中执行,并禁用延迟扩展。但必须使用延迟扩展来扩展LF变量。这就是为什么我在新的cmd.exe会话中显式执行左侧,并通过/v:on
启用了延迟扩展。
另一个选项是JREPL.BAT regular expression text processing utility。它是纯脚本(混合批处理/ JScript),可以在任何Windows机器上从XP开始本地运行 - 不需要第三方exe文件。
我只需要为每个文件调用一次JREPL。
@echo off
setlocal
set "SrcDir=my root directory"
set "FileType=txt"
set "SearchKey=abcdef"
set "LogFile=output.log"
set "find=^\[[^\r\n]*$(?!\r?\n[^\r\n]*%SearchKey%)"
set "repl="
(
for /r "%SrcDir%" %%F in ("test*.%FileType%") do (
echo %%~fF
call jrepl find repl /v /m /match /f "%%F"
echo(
)
) >"%LogFile%"
如果我的要求错误,并且[id]
以下的所有行都应该搜索到下一个[id
],那么FINDSTR解决方案就无法修改工作。但是,通过简单地更改FIND的定义,可以轻松修改JREPL搜索以将搜索范围扩展到下一个[id]
:
set "find=^\[[^\r\n]*$(?!(?:\n(?!\[)|.)*%SearchKey%)"