是否需要针对ms-dos应用程序的查找命令解决方案?

问题描述

我有一些*.bat文件,其中包含find命令来提取某些特定行。

例如,如果我的输入文本文件包含以下内容

Login time : XX:XX
username - XXXXXX
Login time : YY:YY
username - YYYYYYY

使用用户名,免得说:

find /I "XXXXXX" input.txt | find /I "XXXXXX" > output.txt

我能够获得用户名,但不知道如何仅针对搜索到的用户名获得正确的登录时间?

解决方法

find(和findstr)无法处理换行符。他们自己处理每条线。因此,您必须编写一个脚本来记住最后一行,检查当前行中的搜索字符串,并在找到搜索字符串的同时打印最后一行和当前行。

我使用findstr代替了find,因为它更安全(find "XXXXXX"也会找到XXXXXXY)。有关开关findstr /?ix的信息,请参见c

@echo off
setlocal enabledelayedexpansion
set "search=xxxxxx"

for /f "delims=" %%a in (t.txt) do (
  echo %%a|findstr /ixc:"username - %search%" >nul && echo !lastline! %%a
  set "lastline=%%a"
)
,

假设您实际上是在cmd.exe)上工作,而不是在COMMAND.COM)上工作,则可以使用findstr,它可以定义多行搜索字符串,尽管仅在匹配的情况下返回第一行,但是无论如何下一条总是一样的,因此可能不需要。

此Windows 显示了我的意思:

@echo off
rem // Get Carriage-Return (CR) character:
for /F %%C in ('copy /Z "%~f0" nul') do set "CR=%%C"
rem // Get Line-Feed (LF) character:
(set LF=^
%= blank line =%
)
rem // Enable delayed expansion to be able to use CR and LF:
setlocal EnableDelayedExpansion
rem /* Specify a multi-line search string,which must literally reflect the actual
rem    line-break (that is CR + LF for a DOS/Windows text file); `findstr` returns
rem    only the first line when it encounters a match: */
findstr /I /R /C:"!CR!!LF!username - XXXXXX$" "input.txt" > "output.txt"
rem /* This is needed to get the second line of the multi-line match too
rem    (replace this by the commented out line in case you expect multiple entries for
rem    the searched user,because you would get multiple equal user name entries; the
rem    commented out line ensures that there is a single user name entry at the end): */
findstr /I /R /C:"^username - XXXXXX$" "input.txt" >> "output.txt"
rem findstr /I /R /C:"^username - XXXXXX$" "input.txt" | findstr /I /R /V /C:"!CR!!LF!username" >> "output.txt"

N。 B。:
我猜您正在使用两个find命令来摆脱第一个命令产生的标题;但是,您可以改用以下内容:

rem // Input redirection `<` prevents `find` from returning a header:
find /I "XXXXXX" < "input.txt" > "output.txt"