在以设定字符开头的行之间搜索

时间:2017-09-06 13:27:45

标签: windows batch-file

首先,我从未真正使用过批次,但我正在努力完成某些事情并开始感到不知所措。 我在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%"

2 个答案:

答案 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%)"