3

すべて、私はPowerShellに非常に慣れていないので、誰かが私が単純なスクリプトだと思うことを実行できるようになることを望んでいます。

テキストファイルを解析し、そこから特定の行をキャプチャして、それらの行をcsvファイルとして保存する必要があります。

たとえば、各アラートは独自のテキストファイルにあります。各ファイルは次のようになります。

--ファイルの開始---

名前JohnSmithDept
Accounting
Codes bas-2349、cav-3928、deg-3942
            iye-2830、tel-3890
Urls hxxp://blah.com
        hxxp://foo.com、hxxp://foo2.com
一部のテキストI気にしない
より多くのテキスト私は気にしない
コメント
---------
「ここに私が キャプチャ
する必要がある複数行のコメントがあり ます」私が気にしない いくつかのテキスト私が気にしない より多くのテキスト 日付2013年3月12日




---ファイルの終わり---

名前、コード、およびURLのみをCSVファイルに書き込みたい場合は、テキストファイルごとに。誰かが私がこれを始めるのを手伝ってもらえますか?

私はもっ​​とPERLの人なので、Nameで始まる1行をキャプチャするための正規表現を書くことができることを知っています。ただし、「Codes」行が1行である場合や、Urlsフィールドに到達するまでの長さがX行である場合に、どのように「コード」行を読み取ることができるかについて完全に迷っています。

どんな助けでも大歓迎です!

4

5 に答える 5

0

多分これはそれに何かの線があります:

foreach ($Line in gc file.txt) {
    switch -regex ($Line) {
        '^(Name|Dept|Codes|Urls)' {
            $Capture = $true
            break
        }
        '^[A-Za-z0-9_-]+' {
            $Capture = $false
            break
        }
    }
    if ($Capture) {
        $Line
    }
}

最終結果をCSVファイルとして表示する場合は、Export-Csvコマンドレットを使用できます。

于 2013-03-13T07:50:29.843 に答える
0

ファイルがメモリで処理するには大きすぎない場合、簡単な方法は文字列の配列として読み取ることです。(大きすぎるということは、システムによって異なります。サブギガバイトは、あまり問題なく動作するはずです。)

ファイルを読み取った後、要素 0 を指すようにヘッド カウンターとテール カウンターを設定します。日付行が見つかるまで、テール ポインターを行ごとに前方に移動します。データを正規表現と照合できます。これで、1 つのレコードの開始と終了がわかります。次のレコードでは、ヘッド カウンターを tail+1 に設定し、tail を tail+2 に設定して、行のスキャンを再度開始します。泡立て、すすぎ、アレイの最後に到達するまで繰り返します。

レコードが一致すると、正規表現で名前を抽出できます。コードと URL は少しトリッキーです。Codes 行を正規表現と照合します。コードパターンと一致しない限り、それと次のすべての行を抽出します。同じことが URL データにも当てはまります。ファイルが以前の URL とコードのデータである行に空白のパディングを常に持っている場合は、一致する空白数を正規表現で使用して、データ行も取得できます。

于 2013-03-13T07:39:31.710 に答える
0

含まれている事実によるとc:\temp\file.txt

Name John Smith
Dept Accounting
Codes bas-2349,cav-3928,deg-3942
      iye-2830,tel-3890
Urls hxxp://blah.com
     hxxp://foo.com
     hxxp://foo2.com
Some text I dont care about
More text i dont care about
.
.
Date 3/12/2013

次のような正規表現を使用できます。

$a = Get-Content C:\temp\file.txt
$b = [regex]::match($a, "^.*Codes (.*)Urls (.*)Some.*$", "Multiline")
$codes = $b.groups[1].value -replace '[ ]{2,}',','
$urls = $b.groups[2].value -replace '[ ]{2,}',','
于 2013-03-13T21:25:31.890 に答える
0

すべてのファイルが同じ構造を持っている場合、次のようなことができます。

$srcdir  = "C:\Test"
$outfile = "$srcdir\out.csv"

$re = '^Name (.*(?:\r\n .*)*)\r\n' +
      'Dept .*(?:\r\n .*)*\r\n' +
      'Codes (.*(?:\r\n .*)*)\r\n' +
      'Urls (.*(?:\r\n .*)*)' +
      '[\s\S]*$'

Get-ChildItem $srcdir -Filter *.txt | % {
  [io.file]::ReadAllText($_.FullName)
} | Select-String $re | % {
  $f = $_.Matches | % { $_.Groups } | ? { $_.Index -gt 0 }
  New-Object -TypeName PSObject -Prop @{
      'Name'  = $f[0].Value;
      'Codes' = $f[1].Value;
      'Urls'  = $f[2].Value;
    }
} | Export-Csv $outfile -NoTypeInformation
于 2013-03-13T10:18:05.670 に答える
0

通常、テキスト解析は正規表現を意味します。正規表現を使用すると、一致をいつ停止するかを知るためにアンカーが必要になることがあります。これにより、他の方法では気にしないテキストを気にすることができます。「Some text I don't care」の最初の行を指定できれば、それを使用して URL の一致を「固定」し、一致を停止するタイミングを知ることができます。

$regex = @'
(?ms)Name (.+)?
 Dept .+?
 Codes (.+)?
 Urls (.+)?
 Some text I dont care about.+
 Comments
 ---------
 (.+)?
 Some text I dont care about 
'@

$file = 'c:\somedir\somefile.txt'
[IO.File]::ReadAllText($file) -match $regex
if ([IO.File]::ReadAllText($file) -match $regex)
  {
   $Name = $matches[1]
   $Codes = $matches[2] -replace '\s+',','
   $Urls = $matches[3] -replace '\s+',','
   $comment = $matches[4] -replace '\s+',' '
  }

$Name
$Codes
$Urls
$comment
于 2013-03-13T10:18:17.630 に答える