2017-11-03 13 views
1

特定の形式のテキストが多いログファイルがあります。これには、ファイルが進行するにつれて多くの値が割り当てられた特定の変数 'SId'があります。たとえば :バッチファイル - 単語を検索して変数の次の単語を抽出します

For the first line le=24 we have SId = 23 and then, 
on second it's SId = 56, following the be = 45 which...... 

私は、ファイル全体を通読し、変数「のSId」に最後に割り当てられた値を見つけるだろうバッチファイルを作成しようとしています。出来ますか?

+0

このバッチファイルはどのOS用ですか? – Shaun

+0

はい、可能です。あなたは 'FOR/F'コマンドと' FIND'コマンドを使いたいと思っています。 – Squashman

+0

Windowsのコマンドプロンプトに制限されていますか? PowerShellを使用できますか?あなたのログファイルは大きいですか? –

答えて

1

まず、質問に対する回答:はい、可能です。

しかし、私は、質問を読んだ皆さんにとってさらに興味深いと思います。how最後にSIdを取得することができます。まあ、限られたWindowsコマンドインタープリタ機能を使って、データの未知のフォーマットのテキストファイルからこの番号を取得するのは本当に難しいです。その理由から、この純粋で貧弱なタスクの記述は私にとっては興味深いものでした。私はこのコーディングの挑戦を受けました。

は私が3行を次のようにC:\TempにファイルTest File.logを作成:

For the first line we have SId = 23 and then, 
the second line contains nothing interesting despite SId=x8434 
;on third it's "! SId = 56, following SId=8434which ... SId34234 ... !" SId 

最後の行がため、結果として、デフォルトであることeol=;のためので解析されたライン上の問題があるセミコロンで始まりますそのような行はデフォルトでは無視されます。

最後の行には、この行の処理で遅延環境変数の拡張が必要な​​二重引用符も含まれています。また、2つの感嘆符は、遅延拡張を有効にしてこの行を処理しても、 。

最後の行には、SIdも含まれています。最初の2つのSIdは等号の周りにさまざまな数のスペースがあり、3番目のSIdは等号なしで無視され、最後にはSIdの後にスペースが1つしかありません。

以下のバッチコードは、有効な読者のためにコメントされていますが、最後の有効数字から番号を特定するコードブロックは例外です。SId。コードのその部分は、バッチプログラミングの初心者にとって説明するのが本当に難しいです。バッチファイルの先頭から@echo offを削除し、コマンドプロンプトウィンドウ内からバッチファイルを実行し、出力コマンドラインを調べることで、このコードの動作を理解することは間違いありません。ループサブルーチンGetNumber FOR

ProcessLineブロックは、値と例をTest File.log 4回実行される。

= 56, following SId=8434which ... SId34234 ... !" SId 
=8434which ... SId34234 ... !" SId 
34234 ... !" SId 
  

注:Valueは末尾のスペースで終わります。

この非常に一般的に説明したタスク用のバッチコード:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 
set "LogFile=C:\Temp\Test File.log" 
if not exist "%LogFile%" goto EndBatch 

rem Use command FINDSTR to search for all lines containing case-sensitive 
rem the string "SId = " without or with spaces around the equal sign and 
rem at least one digit. Output by FINDSTR are the lines matching this regular 
rem expression with line number and a colon at beginning because of option /N. 
rem The option /N is used to make sure that no line with SId starts with a 
rem semicolon as those lines would be ignored by default by FOR. The last 
rem line with a string matching this simple regular expression is assigned 
rem to variable LastLine. Otherwise this environment variable deleted 
rem before the loop still does not exist after the loop finished. 

set "LastLine=" 
for /F "delims=" %%I in ('%SystemRoot%\System32\findstr.exe /N /R /C:"SId *= *[]" "%LogFile%"') do set "LastLine=%%I" 
if not defined LastLine goto EndBatch 

rem The last line contains perhaps multiple times an equal sign and perhaps 
rem even multiple "SId" (secure identifier) strings. So it is necessary to 
rem process this last line really the hard way. And it is better to process 
rem the line perhaps containing also double quotes or other characters with 
rem a special meaning for the Windows command interpreter using delayed 
rem environment variable expansion. 

setlocal EnableDelayedExpansion 
set "Identifier=" 

:ProcessLine 
set "Value=!LastLine:*SID=!" 
if not defined Value goto LineProcessed 
if "!Value!" == "!LastLine!" goto LineProcessed 

for /F "tokens=1,2" %%A in ("!Value!") do (
    set "LastID=" 
    if "%%A" == "=" (
     set "Number=%%B" 
     call :GetNumber 
    ) else (
     set "Number=%%A" 
     if "!Number:~0,1!" == "=" (
      set "Number=!Number:~1!" 
      call :GetNumber 
     ) 
    ) 
    if defined LastID set "Identifier=!LastID!" 
    set "LastLine=!Value!" 
    goto ProcessLine 
) 
set "LastLine=!Value!" 
goto ProcessLine 

:GetNumber 
if not defined Number goto :EOF 
set "IsDigit=1" 
for /F "delims=" %%I in ("!Number:~0,1!") do set "IsDigit=0" 
if %IsDigit% == 0 goto :EOF 
set "LastID=%LastID%%Number:~0,1%" 
set "Number=!Number:~1!" 
goto GetNumber 

rem Pass the last found identifier from current environment with delayed 
rem expansion to previous environment on restoring previous environment. 

:LineProcessed 
endlocal & set "Identifier=%Identifier%" 
if not defined Identifier goto EndBatch 

echo Last SId found: %Identifier% 

rem Other command lines which process the found identifier. 

:EndBatch 
endlocal 

は、たとえばTest File.logため、このバッチファイルの出力は次のとおりです。使用するコマンドとその仕組みを理解するための

Last SId found: 8434 

、オープンコマンドプロンプトウィンドウを開き、次のコマンドを実行し、各コマンドに表示されているすべてのヘルプページを完全に読み込みます。

  • call /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?

Single line with multiple commands using Windows batch file 1つのコマンドラインで使用されるよう&オペレータを説明する図です。

0

実際のログファイルの内容を見なければ、堅牢な例を提供することは困難であろうが、一般的にSIdは各行の最初の文字列の場合、以下の2つのFindStrの例の一つがあればよい:

@For /F "Tokens=1,3" %%A In ('FindStr/BRC:"SId[ ]=[ ][0-9]*" "file.log"') Do @Set "%%A=%%B" 
@Echo %SId% 
@Pause 

@For /F "Tokens=1,3" %%A In ('FindStr/RC:"^SId\ =\ [0-9]*" "file.log"') Do @Set "%%A=%%B" 
@Echo %SId% 
@Pause 

あなたの最後の値は%SId%という名前の変数に割り当てられます。ログファイルの名前にfile.logを使用しましたが、必要に応じて調整してください。 FindStrのオプション/スイッチを検索するには、コマンドプロンプトでFindStr/?と入力します。

0

バッチは本当にそのようなもののために作られていません。以下は、いくつかのものに依存します:
- SId=の間のスペースとスペースが=後にあります(find文字列を変更することができます)
- 有効な区切り文字(スペース、タブ、カンマ、=)があります値または値の後に行の最後のものです。

@echo off 
SETLOCAL EnableDelayedExpansion 
for /f "delims=" %%a in ('type t.txt^|find "SId = "') do (
    set "line=%%a" 
    set "line=!line:*SId =! 
    set /a "last=!line:~1!" 2>nul 
) 
echo %last% 

トリックは、検索文字列(悲しいこと=はこれで削除することはできません)、その後、残りの部分を使用して(マイナス=で最初の文字、)(を含む)に最初から何かを削除することです数値を変数に代入するにはset /aを使用します。
NULにリダイレクトされる番号の後に文字列部分がある場合は、「オペランドがありません」というエラーメッセージがあります。

関連する問題