【问题标题】:Loop recursively into subfolders and look for a substring into files递归循环到子文件夹并在文件中查找子字符串
【发布时间】:2016-12-22 17:00:36
【问题描述】:

我想创建一个脚本,递归循环通过D:\MyFolder\ 的子文件夹,例如,查找多个名为MyFile.txt 的文件 然后在每个文件中查找关键字FROM 并检索FROM 和下一个分号; 之间的字符串。

MyFile.txt 的示例:

LOAD
   Thing1,
   Thing2,
   Thing3,
FROM
   Somewhere ;

想要的结果是:Somewhere

(分号;的位置可以在另一行)。

我做了一些尝试,但没有成功编写出正确的脚本:

@echo off
SET PATH="D:\MyFolder\"
FOR /R %PATH% %%f IN (MyFile.txt) DO (
    FOR /F "delims=FROM eol=;" %%A in (%%f) do (
    set str=%%A
    ECHO %str% 
    )
)

如果不能批量完成,请告诉我用哪种语言可以轻松完成。最后我想有一个可执行的脚本。

【问题讨论】:

  • for /Fdelims 选项定义了 characters 而不是 words 用作解析文本文件的分隔符;使用findstr检索关键字FROM的位置(行号,选项/N); FROM; 之间的字符串可以包含多行吗?如果是这样,只需连接它们?每个文件是否总是出现一次FROM
  • 我尝试使用 findstr 但执行脚本时无法识别,“findstr 未被识别为内部或外部命令”
  • 是的,FROM; 之间的字符串可以多行。每个文件中多次出现FROM
  • 我相信,你搞砸了你的 %path% 变量...不要使用 %path% 作为变量名 - cmd 使用它来查找它的可执行文件。

标签: windows batch-file for-loop substring


【解决方案1】:

您的代码中存在一些问题:

  • for /Fdelims 选项定义字符,但不是单词,以用作解析文本文件的分隔符。要查找单词,请改用findstr(您可以使用其/N 选项来导出搜索字符串的位置/行号)。
  • for /Feol 选项定义了一个字符,如果它出现在开头(或者它前面只有定界符),则忽略它。
  • 如果集合中没有通配符(?*)(即括号之间的部分),for /R 实际上不会搜索文件。 dir /S 命令确实如此,因此您可以通过在 dir /S 周围包裹一个 for /F 循环来解决此问题。
  • PATH变量是系统用来查找可执行文件的,比如findstr,所以不能覆盖它;请改用其他变量名。

这是我可能会这样做的方式(假设关键字FROM 后面的任何文本也需要返回):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_ROOT=D:\MyFolder" & rem // (root directory of the tree to find files)
set "_FILE=MyFile.txt"  & rem // (name of the files to find in the tree)
set "_WORD=FROM"        & rem // (keyword to be searched within the files)
set "_CHAR=;"           & rem // (character to be searched within the files)

rem // Walk through the directory tree and find matching files:
for /F "delims=" %%F in ('dir /B /S "%_ROOT%\%_FILE%"') do (
    rem // Retrieve the line number of each occurrence of the keyword:
    for /F "delims=:" %%N in ('findstr /N /I /R "\<%_WORD%\>" "%%~F"') do (
        rem // Process each occurrence of the keyword in a sub-routine:
        call :PROCESS "%%~F" %%N
    )
)

endlocal
exit /B


:PROCESS
rem // Ensure the line number to be numeric and build `skip` option string:
set /A "SKIP=%~2-1"
if %SKIP% GTR 0 (set "SKIP=skip^=%SKIP%") else set "SKIP="
rem // Read file starting from line containing the found keyword:
set "FRST=#"
for /F usebackq^ %SKIP%^ delims^=^ eol^= %%L in ("%~1") do (
    set "LINE=%%L"
    setlocal EnableDelayedExpansion
    rem // Split off everything up to the keyword from the first iterated line:
    if defined FRST set "LINE=!LINE:*%_WORD%=!"
    rem /* Split read line at the first occurrence of the split character;
    rem    the line string is augmented by preceding and appending a space,
    rem    so it is possible to detect whether a split char. is there: */
    for /F "tokens=1,* delims=%_CHAR% eol=%_CHAR%" %%S in (" !LINE! ") do (
        endlocal
        set "TEXT=%%S"
        set "RMND=%%T"
        set "ITEM=%~1"
        setlocal EnableDelayedExpansion
        rem // Check whether a split character is included in the line string:
        if not defined RMND (
            rem // No split char. found, so get string without surrounding spaces:
            set "TEXT=!TEXT:~1,-1!"
        ) else (
            rem // Split char. found, so get string without leading space:
            set "TEXT=!TEXT:~1!"
        )
        rem // Trimm leading white-spaces:
        for /F "tokens=*" %%E in ("!TEXT!") do (
            endlocal
            set "TEXT=%%E"
            setlocal EnableDelayedExpansion
        )
        rem // Return string in case it is not empty:
        if defined TEXT echo(!ITEM!;!TEXT!
        rem // Leave sub-routine in case split char. has been found:
        if defined RMND exit /B
    )
    endlocal
    set "FRST="
)
exit /B

【讨论】:

  • 感谢您的回复,我正在尝试调整您的代码以满足我的需要,为了将我的结果放入文本文件中,我将输出重定向到 log.txt,并添加了路径我们循环遍历的文件夹,如下所示: echo(%%~F;!TEXT:~1,-1!)>> log.txt 。可以吗?正如您所说,当 FROM 关键字在单独的行中时它起作用,我真正需要的是不跳过任何行。当我弄乱跳过选项时,我得到了奇怪的结果。我应该改变哪个选项?
  • 我稍微更改了脚本以在输出中包含当前文件路径。要记录结果,只需重定向整个批处理脚本,如script.bat &gt; log.txt(使用&gt;&gt; 追加而不是覆盖)。所以你希望包含FROM 的行也包含在输出中?
  • 是的,我想包括“FROM”后面的所有字符串,无论它是在同一行还是在单独的行中。解析后的文件是代码文件(QlikView Code),根据开发者如何缩进代码,“FROM”后面的字符串可以放在同一行,像这样: FROM [somewhere in the disk] ; .或行后,如果他放了一些换行符。 FROM [磁盘中的某处] ;
  • 查看我的edit,它现在应该反映了您的所有要求...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
相关资源
最近更新 更多