2

次のテキストのすべての行を FINDSTR /R と一致させたい

LABO_A =
  (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = host01)(PORT = 1521))
    (CONNECT_DATA =
      (SERVICE_NAME = LABO)
    )
  )

既に試しました Windows FINDSTR コマンドの文書化されていない機能と制限は何ですか? 特に「改行をまたぐ検索」の部分。しかし、残念ながらうまくいきませんでした。

私のアプローチは次のとおりです。

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 のパラメーターを調整しました。

今では動作します。

4

3 に答える 3

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 文字列長を超えました。

于 2013-11-08T19:56:39.143 に答える
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がそれが next-line-expected と一致するかどうかを確認します。

IF NOTステートメントは重要です-そして一見非論理的です(必要に応じて大文字と小文字を区別しないようにするためにスイッチを追加する必要が/iあり%hits%ます... が実行されるため、不一致が見つかった場合は 0 にリセットされます。カウントが 1 でない場合、テストが繰り返されますこれでケースが処理されますhitshitsHITS

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」が予期されていたときに、2 番目の「行 1」が検出されます。HITSは 0 に変更されますが、それは4だったので、実行は に戻り、テストは=1:testで繰り返されます。HITS

別のアプローチは、行を別の配列 (たとえば ) に読み込み、一致するエントリL#*をテストすることでした。一致しない場合は、リップルアップして次の読み取り行を... に割り当てますが、それは後で考えました。おそらく、より簡単でより良いものになるでしょう - 興味のある人のための演習として残しておきます。L_*L#*%LINES%L#!lines!

于 2013-11-08T14:31:02.957 に答える
0

これは、参照の後にある場合に機能しLABO_Aます。

https://www.dropbox.com/s/rfdldmcb6vwi9xc/findrepl.batfindrepl.batから呼び出されるヘルパー バッチ ファイルを使用します。

findrepl.batバッチ ファイルと同じフォルダーまたはパス上に配置します。

type "file.txt" | findrepl "^LABO_A =" /e:"^  \)"
于 2013-11-08T16:20:28.907 に答える