我有很多带有一些内容的文本文件。首先,我想在全球范围内编号。然后我提取了所有在某处复制的行(在任何给定文件中出现至少两次)。但是现在我需要用这行第一次出现的文件名和行号来标记所有这些行。现在有趣的部分 - 它需要是一个Windows批处理文件,使用本机Windows工具。这就是我开始遇到这个问题的原因。
所以,总结一下:
我有一个带有唯一字符串/行的 A 文件,据说每个文件在给定的文件集中至少出现两次。
我需要搜索这些文件,并用 A 文件标记所有出现的给定行 - 首次出现该行的文件名 该文件中的行号
这是我的代码,努力为行和格式文件编号。
@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
答案 0 :(得分: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
然后它执行findstr
以在/c:"%%s"
或文字模式(即不使用正则表达式)中找到%%s
完整字符串/l
(包括任何空格) /b
和/e
以目标开头和结尾的行(即完全匹配)和/n
对这些行进行编号。
findstr的输出格式为linenumber:linecontents
,因此如果FOR
使用选项"delims=:"
检查此行,那么部分直到第一个:
被分配到%%L
所以 - %%L
包含行#,%%f
文件名,%%s
字符串
通过将其值设置为[nothing]来清除检测到此行的searching
意味着它不是NOT DEFINED
因此不会从当前文件报告更多行,并且不会检查其他文件名。
现在,如果您想获得目标线的所有出现的列表,您需要做的就是删除SET "searching="
行。然后将永远不会重置搜索,因此会报告每个文件中的每一行。
如果您想要其他组合,请澄清。
我完全不知道“标记”一条线是什么意思。
答案 1 :(得分: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
上面的Batch程序会忽略输入文件中的空行,如果它们包含特殊的批处理字符,则会失败,例如! & < > |
;如果需要,可以修复此限制。
答案 2 :(得分: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.
)
脚本可以处理!&<>|%
,但不能处理=
。