我想将以下文本的所有行与FINDSTR / R
匹配LABO_A =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = host01)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = LABO)
)
)
我已经尝试What are the undocumented features and limitations of the Windows FINDSTR command? 特别是“搜索跨线休息”部分。但不幸的是它没有用。
我的方法如下:
SETLOCAL
set LF=^
FOR /F %%A IN ('COPY /Z "%~dpf0" NUL') DO SET "CR=%%A"
SETLOCAL enableDelayedExpansion
FINDSTR /R "LABO_A.=.!CR!*!LF!.*(DESCRIPTION.=.!CR!*!LF!.*(ADDRESS.=.(PROTOCOL.=.TCP)(HOST.=.host01)(PORT.=.1521))!CR!*!LF!.*(CONNECT_DATA.=!CR!*!LF!.*(SERVICE_NAME.=.LABO)!CR!*!LF!.*)!CR!*!LF!.*)" %FINDPATH%
我错过了什么吗?或者批量正则表达式是不是足以实现这一点?
解: @dbenham的方法让我重新考虑我的正则表达式字符串。所以我将其编辑为
FINDSTR /R /C:"LABO_A =!CR!*!LF!.*(DESCRIPTION =!CR!*!LF!.*(ADDRESS = (PROTOCOL = TCP)(HOST = host01)(PORT = 1521))!CR!*!LF!.*(CONNECT_DATA =!CR!*!LF!.*(SERVICE_NAME = LABO)!CR!*!LF!.*)!CR!*!LF!.*)" %FINDPATH% > NUL
我删除了一些不必要的空格并调整了FINDSTR的参数。
现在可行。
答案 0 :(得分:2)
你的正则表达式错了。您的源代码行在=
之后立即结束,但正则表达式中的额外.
正在=
之后查找其他字符。
我认为您使用.
来表示空白区域。我认为你最好使用实际空格,但是你需要/C
选项。
以下内容成功匹配。
@echo off
SETLOCAL
set LF=^
FOR /F %%A IN ('COPY /Z "%~dpf0" NUL') DO SET "CR=%%A"
SETLOCAL enableDelayedExpansion
FINDSTR /R /C:"LABO_A =!CR!*!LF! *(DESCRIPTION =!CR!*!LF! *(ADDRESS = (PROTOCOL = TCP)(HOST = host01)(PORT = 1521))!CR!*!LF! *(CONNECT_DATA =!CR!*!LF! *(SERVICE_NAME = LABO)!CR!*!LF! *)!CR!*!LF! *)" test.txt
请注意,即使正则表达式中的所有行都匹配,也只会打印匹配集的第一行。
我怀疑配置文件中不需要换行符。这是另一种允许更多白色空间变化的变体。
@echo off
setlocal enableDelayedExpansion
set LF=^
FOR /F %%A IN ('COPY /Z "%~dpf0" NUL') DO SET "CR=%%A"
set "ws=[ !cr!!lf!]*"
FINDSTR /RX /C:"LABO_A =!ws!(DESCRIPTION =!ws!(ADDRESS = (PROTOCOL = TCP)(HOST = host01)(PORT = 1521))!ws!(CONNECT_DATA =!ws!(SERVICE_NAME = LABO)!ws!)!ws!)!ws!" test.txt
我还尝试在我认为可能的每个地方允许空格,但这超出了FINDSTR的最大REGEX字符串长度。
答案 1 :(得分:1)
基本上,批处理正则表达式不够强大。毫无疑问,SED
会更好。
尽管如此,这是一种检测文件中出现一系列行的方法。它有点受限制,但应该足以满足你提名的顺序。它假定前导空格不重要。
@ECHO OFF
SETLOCAL enabledelayedexpansion
FOR /f "delims==" %%a IN ('set l_ 2^>nul') DO "SET %%a="
SET /a lines=0
FOR /f "tokens=*" %%a IN (q19859936.txt) DO SET /a lines+=1&SET l_!lines!=%%a
SET hits=0
SET "stop="
FOR /f "tokens=*" %%a IN (q19859936.test) DO (
SET l_0=%%~a
CALL :test
IF DEFINED stop GOTO done
)
:done
IF DEFINED stop (ECHO FOUND ) ELSE (ECHO NOT FOUND)
GOTO :EOF
:test
SET /a hits+=1
ECHO IF NOT "!l_%hits%!"=="%l_0%"
IF NOT "!l_%hits%!"=="%l_0%" SET hits=0&IF %hits%==1 (GOTO :eof) ELSE (GOTO test)
IF %hits%==%lines% SET stop=Y
GOTO :eof
[编辑代码20131111T1408Z - 首先FOR
有tokens=2
]
初始FOR
可确保清除变量L_*
。
文件q19859936.txt
被读取为要检测的行序列。
q19859936.test
。每行依次分配给L_0
,内部子程序:test
将检查它是否与预期的下一行匹配。
IF NOT
语句很重要 - 而且看似不合逻辑(如果你想要的话,你需要添加/i
开关以使其不区分大小写...)当批处理解析该行时, %hits%
被当前的hits
值和 THEN 替换,执行该行,如果发现不匹配,hits
将重置为0 。如果HITS
计数 WAS 不是1,则重复测试。这样可以处理案例
matches line 1
matches line 2
matches line 3
matches line 1
matches line 2
matches line 3
matches line 4
matches line 5
matches line 6
当预期“第4行”时遇到第二个“第1行”。因此HITS
更改为0,但 WAS 4,因此执行会返回:test
,并且HITS
= 1重复测试。
另一种方法可能是将行读入另一个数组(比如L#*
)并测试L_*
匹配L#*
,用于%LINES%
条目。在没有匹配的情况下,波及并将下一行读取分配给L#!lines!
...但我后来想到了。可能也会更容易和更好 - 我会把它作为锻炼给任何可能感兴趣的人。
答案 2 :(得分:0)
如果您在LABO_A
参考之后,这将有效。
它使用来自 - https://www.dropbox.com/s/rfdldmcb6vwi9xc/findrepl.bat
的名为findrepl.bat
的帮助程序批处理文件
将findrepl.bat
放在与批处理文件相同的文件夹中或路径上。
type "file.txt" | findrepl "^LABO_A =" /e:"^ \)"