2017-07-06 3 views
1

Powershellスクリプトの初心者ですが、私は単純な答えを見落としていると感じています。Powershellを使ってtxtファイルの特定のセクションを取得する

私の会社は、マップされたネットワークプリンタの中間付近のセクションを持つすべてのコンピュータからファイルをエクスポートします。それは次のようになります。

------------------------------------------------------------------------- 
Mapped Network Printers: 
NetworkAddress\HP425DN [DEFAULT PRINTER] 
------------------------------------------------------------------------- 
Local Printers: 

は、私は何を求められていることは新しいテキストファイルにコピーだけでマップされたネットワークプリンタです。

コンテキストパラメータでSelect-Stringを使用しようとしましたが、ネットワークプリンタの数がわからないので推測できません。

また、私は、このサイトにある次のコードを使用してみましたが、それは何も返しません:

$MapPrint = gc C:\Users\User1\Documents\Config.txt 

$from = ($MapPrint | Select-String -pattern "Mapped Network Printers:" | 
Select-Object LineNumber).LineNumber 
$to = ($MapPrint | Select-String -pattern "------------------------------- 
--------------------------------------------" | Select-Object 
LineNumber).LineNumber 

$i = 0 
$array = @() 
foreach ($line in $MapPrint) 
{ 
foreach-object { $i++ } 
    if (($i -gt $from) -and ($i -lt $to)) 
    { 
    $array += $line  
    } 
} 
$array 

は、私は基本的に「マップされたネットワークプリンタ」で検索を開始し、次の行でそれを終了します"------"

ご協力いただければ幸いです。

答えて

0

Select-String内容に基づいて、ラインの範囲を抽出するための機能を持っていない

最も簡単な方法は、全体としてファイルを読み取り、正規表現(正規表現)を介して、範囲を抽出する-replace演算子を使用することである。

$file = 'C:\Users\User1\Documents\Config.txt' 
$regex = '(?sm).*^Mapped Network Printers:\r?\n(.*?)\r?\n---------------------.*' 
(Get-Content -Raw $file) -replace $regex, '$1' 

全体として入力ファイルを読み取ることができます大きすぎてメモリに収まらないファイルでは問題がありますが、おそらくそれはあなたの心配ではありません。
このアプローチは、ループの行を処理するよりもはるかに高速です。

  • Get-Content -Raw(PSV3 +)全体として入力ファイルを読み出します。

  • インライン正規表現オプション(?sm)M ultiラインの両方の電源をオンにし、Sイングルラインオプション:

    • m手段^$一致各ラインの開始及び終了その入力文字列全体ではなく、です。
    • s発現など.*はライン横切っを一致させるために使用することができるように.メタ文字は、あまりに\n文字と一致することを意味します。
  • \r?\nは、CRLFとLFの両方の改行に一致します。

  • (.*?)は、境界線の間のすべてをキャプチャする(貪欲ではない)キャプチャグループです。正規表現は、全体入力文字列と一致し、そしてその後、第1の(そして唯一の)捕捉基($1)に捕捉関心のちょうどストリング(範囲)に置き換えられていること

  • 注。

$fileが含まれていると仮定すると:

------------------------------------------------------------------------- 
Mapped Network Printers: 
NetworkAddress\HP425DN [DEFAULT PRINTER] 
NetworkAddress\HP426DN 
------------------------------------------------------------------------- 
Local Printers: 

上記利回り:

NetworkAddress\HP425DN [DEFAULT PRINTER] 
NetworkAddress\HP426DN 
0

\の単語を探すには、Select-StringまたはWhere-Objectを使用できます。これは、サーバー名とプリンタだけでAZを使用し、0-9の仮定を作る

Get-Content C:\Users\User1\Documents\Config.txt -Raw | 
    Select-String '[A-Z0-9]+\\[A-Z0-9]+' -AllMatches | 
    ForEach-Object {$_.Matches.Value} 

注こと、あなたが探しする必要があります。さらに、あなたがこのような正規表現を持つだけserver\printer値を探すことができることを取りますそれが有効な前提でないならば、より多くの文字。ここで

はあなたがforeach-objectコマンドといくつかの追加の試験条件で試みている何ができる\

Get-Content 'C:\Users\User1\Documents\Config.txt' | Where-Object {$_ -like '*\*'} 
0
$Doc= "C:\temp\test.txt" 
$Doc_end ="C:\temp\testfiltered.txt" 
$reader = [System.IO.File]::OpenText($Doc) 

$cdata="" 
while($null -ne ($line = $reader.ReadLine())) 
    { 

     if ($line -like ('---*'))  {$Read = 0 } 

     if ($Read -eq 1) {$cdata+= $line + "`r`n"} 

     if ($line -like ('Mapped Network Printers:*')) {$Read = 1} 


    } 


$cdata | Out-File $Doc_end -Force 
0

で行をフィルタリングするWhere-Objectを使用した例だろう。 Mapped Network Printers:行に遭遇し、次の行の出力を終了するときに単にフラグを設定すると、-like "---*"が動作します。

## positional parameters 
param(
    [Parameter(Mandatory=$true)][string]$infile 
) 
$beginprn = 0 

get-content $infile | foreach-object { 
    # terminate condition 
    if ([int]$beginprn -eq 1 -and $_ -like "---*") { 
     break 
    } 
    # output Mapped printers 
    if ([int]$beginprn -eq 1) { 
     write-host $_ 
    } 
    # begin condition 
    if ($_ -eq "Mapped Network Printers:") { 
     $beginprn = 1 
    } 
} 

例入力ファイル

------------------------------------------------------------------------- 
Mapped Network Printers: 
NetworkAddress\HP425DN [DEFAULT PRINTER] 
NetworkAddress\HP4100N 
------------------------------------------------------------------------- 
Local Printers: 

使用例/出力

PS> parseprn.ps1 .\tmp\prnfile.txt 
NetworkAddress\HP425DN [DEFAULT PRINTER] 
NetworkAddress\HP4100N 
関連する問題