Как я могу использовать findstr с регулярным выражением новой строки - PullRequest
2 голосов
/ 12 апреля 2011

Я на Windows DOS подскажите. У меня есть файл журнала, который содержит журнал, как:

Timestamp: Order received for Item No. 26551
Timestamp: Exception: OutOfRangeException
Timestamp: Message: Inventory Item is not stock. Item No. 23423
Timestamp: Order received for Item No. 23341

Я хочу извлечь номер элемента, который дал какое-то исключение. Я использую команду findstr для этого. Как я могу использовать новую строку в моем регулярном выражении? Я хочу, чтобы во всех строках было слово Исключение, а со следующей строки номер позиции

любая помощь?

Ответы [ 4 ]

4 голосов
/ 08 января 2012

Я обнаружил недокументированную функцию - FINDSTR CAN сопоставляет символы новой строки <CR> и <LF> и продолжает сопоставление на последующих строках. Но строка поиска должна быть указана в командной строке, символы новой строки должны быть в переменных, а значения должны быть переданы с помощью отложенного расширения.

Еще одним осложнением является предложение IN () цикла FOR, выполняемое в отдельном неявном сеансе CMD, и отложенное расширение должно быть повторно включено. Так же ! символы должны быть экранированы, чтобы они могли пройти во 2-й сеанс CMD.

Этот маленький тестовый скрипт делает свое дело.

@echo off
setlocal enableDelayedExpansion
if "%~1"==":doSearch" goto :doSearch

::Define a variable as a LineFeed (0x0A) character
set LF=^


:: The above 2 blank lines MUST be preserved!

::Define a CR variable as a CarriageReturn (0x0D) character
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

set file="test.txt"
for /f "delims=" %%A in ('cmd /v:on /c^"findstr /rc:"Item No\. .*^!CR^!*^!LF^!.* Exception: " %file%^"') do (
  set "ln=%%A"
  set "item=!ln:*Item No. =!"
  echo Item No. !item! had an exception
)
exit /b


РЕДАКТИРОВАТЬ 2015-01-11

Я просто перечитал вопрос и понял, что понял неправильно. Оператор запрашивал номер элемента, в котором строка «Исключение» появляется в предыдущей строке (посмотрите за поиском), но мое решение может найти только номер элемента, в котором исключение появляется в следующей строке (поиск в перспективе).

К сожалению, нет способа заставить FINDSTR выполнить поиск за поиском.

В большинстве случаев я бы удалил ответ выше, поскольку он не отвечает на вопрос. Однако этот ответ документирует новую функциональность FINDSTR, которая не была описана ранее, что может быть очень полезным. Функция просмотра в будущее достаточно близка по своей сути к функции поиска за спиной, так что кто-то, кому она нужна, может найти ответ по этому вопросу, поэтому я планирую оставить ее.

У меня есть решение, основанное исключительно на сценариях, которое работает на любом компьютере с Windows начиная с XP, но не использует FINDSTR. JREPL.BAT - это командная строка регулярного выражения, которая может легко извлечь нужные номера элементов.

jrepl "Item No\. (\d+)\r\n.* Exception: " $1 /m /jmatch /f test.txt
1 голос
/ 12 апреля 2011

Я заглянул в документацию findstr и думаю, что он не может выполнять многострочный поиск.

Возможно, вам следует использовать более продвинутые инструменты, такие как awk, или некоторые версии grep также поддерживают многострочное регулярное выражение.

Вы можете взглянуть на stackoverflow.com / questions / 152708 /

0 голосов
/ 12 апреля 2011

Если вы можете скачать инструменты, вот команда Ruby для Windows , которую вы можете использовать.

C:\work>ruby -ne "print gets.split.last if /Exception/" file
23423
C:\work>type file
Timestamp: Order received for Item No. 26551
Timestamp: Exception: OutOfRangeException
Timestamp: Message: Inventory Item is not stock. Item No. 23423
Timestamp: Order received for Item No. 23341

C:\work>ruby -ne "print gets.split.last if /Exception/" file
23423
0 голосов
/ 12 апреля 2011

Если вы работаете в Vista или Windows 7 (или устанавливаете его вручную в XP), вы можете использовать PowerShell для этого:

$resultlist = new-object System.Collections.Specialized.StringCollection
$regex = [regex] '(?m)^.*Exception.*\r\n.*Item No\. (\d+)'
$match = $regex.Match($subject)
while ($match.Success) {
    $resultlist.Add($match.Groups[1].Value) | out-null
    $match = $match.NextMatch()
} 

$resultlist будет содержать список всех номеров позицийкоторые следуют за линией с Exception в нем.

...