0

我有一堆包含一些内容的文本文件。首先,我想在全球范围内对线路进行编号。然后我提取了在某处重复的所有行(在任何给定文件中至少出现两次)。但是现在我需要用该行第一次出现的文件名和行号来标记所有这些行。现在有趣的部分 - 它需要是一个 Windows 批处理文件,使用本机 Windows 工具。这就是为什么我一开始就有这个问题。

所以,总结一下:

我有一个文件A,据说它们中的每一个在给定的文件集中至少出现两次。

我需要搜索这些文件并标记A中所有出现的给定行文件中标记所有出现的给定行,其中该行首先出现在该文件中的行号 -file name

这是我努力编号行和格式化文件的代码。

@echo off
setlocal EnableDelayedExpansion
set /a lnum=0
if not [%1]==[] pushd %1

for /r %%F in (*.txt) do call :sub "%%F"
echo Total lines in %Files% files: %Total%
popd
exit /b 0
:Sub
set /a Cnt=0

for /f %%n in ('type %1') do (
  set /a Cnt+=1
  set /a lnum=!lnum!+1
  echo ^<!lnum!^> %%n >> %1_ln.txt && echo ^<!lnum!^> >> %1_ln.txt && echo. >> %1_ln.txt
)
set /a Total+=Cnt
set /a Files+=1
echo %1: %Cnt% lines
4

3 回答 3

0
@echo off
setlocal EnableDelayedExpansion
set lnum=0
if not "%~1" == "" pushd %1

rem "I've got bunch of text files..." (%%F is file name)
for /r %%F in (*.txt) do call :sub "%%F"
echo Total lines in %Files% files: %lnum%
popd
exit /b 0


:Sub "filename"
set Cnt=0

rem "... with some content." (%%n is line contents)
(for /f "usebackq delims=" %%n in (%1) do (
   set /a Cnt+=1
   rem "First I wanted to number the lines globally."
   set /a lnum+=1
   echo ^<!lnum!^> %%n 
   rem "Then I extracted all lines that are duplicated somewhere" (that were defined before)
   if defined line[%%n] (
      rem "I need to mark all of these lines with the filename and line number of the first occurrence of this line."
      echo ^<!line[%%n]!^>
      echo/
   ) else (
      REM (Store the first occurrence of this line with *local* line number and filename)
      set line[%%n]=!Cnt!: %1
   )
)) > "%~PN1_ln.txt"
set /A Files+=1
echo %1: %Cnt% lines
exit /B

上面的批处理程序会忽略输入文件中的空行,如果它们包含特殊的批处理字符,例如! & < > |; 如果需要,可以修复此限制。

于 2013-04-19T08:18:18.697 回答
0
@ECHO OFF & setlocal
for /f "tokens=1*delims==" %%i in ('set "$" 2^>nul') do set "%%i="

for %%a in (*.txt) do (
 for /f %%b in ('find /v /c "" ^<"%%a"') do echo(%%b lines in %%a.
 set /a counter=0, files+=1
 for /f "usebackqdelims=" %%b in ("%%~a") do (
    set /a counter+=1, total+=1
    set "line=%%b"
    setlocal enabledelayedexpansion
    if not defined $!line! set "$!line!=%%a=!counter!=!line!"
    for /f "delims=" %%i in ('set "$" 2^>nul') do (if "!"=="" endlocal)& set "%%i"
    )
)
echo(%total% lines in %files% files.
for /f "delims=" %%a in (a) do set "#%%a=%%a"
for /f "tokens=2,3*delims==:" %%i in ('set "$" 2^>nul') do (
    if defined #%%k echo("%%k" found in %%i at line %%j.
)

脚本可以处理!&<>|%,但不行=

于 2013-04-19T14:07:15.247 回答
0
@ECHO OFF
SETLOCAL

FOR /f "delims=" %%s IN (A) DO (
 SET searching=Y
 FOR /f "delims=" %%f IN (
  'dir /s /b /a-d *.txt') DO IF DEFINED searching (
  FOR /f "tokens=1delims=:" %%L IN (
   'findstr /b /e /n /l /c:"%%s" ^<"%%f"') DO IF DEFINED searching (
ECHO Line %%L IN "%%f" FOUND "%%s"
SET "searching="
 )
 )
)

这是一个例行程序的核心,它应该做你正在寻找的事情——这就像泥巴一样清晰。

它依次查看每个字符串的“A”文件,将字符串分配给%%s并设置标志searching

然后它查看文件列表,将文件名分配给%%f

然后它执行 a以在或文字模式(即不使用正则表达式)中findstr查找/c:"%%s"完整的字符串%%s(包括任何空格),以查找以目标开头和结尾的行(即完全匹配)并对这些行编号。/l/b/e/n

findstr 的输出将采用格式,因此如果使用选项linenumber:linecontents检查此行,则将第一个分区分配给FOR"delims=:":%%L

所以 -%%L包含行号、%%f文件名、%%s字符串 Clearingsearching通过将其值设置为 [nothing] 检测到该行意味着它不是,NOT DEFINED因此不会从当前文件报告更多行,也不会检查更多文件名。

现在,如果您想获得目标行的所有出现的列表,您需要做的就是 REM-out 该SET "searching="行。搜索将永远不会被重置,因此会报告每个文件中的每一行。

如果您想要其他组合,请澄清。

我完全不知道“标记”一条线是什么意思。

于 2013-04-19T06:17:31.587 回答