2017-11-07 25 views
0

私は初心者です。私は2列のデータを含むテキストファイルを持っています。 1つの列はベンダーであり、1つは請求書です。 このテキストファイルを1行ずつスキャンし、パス内のベンダーと請求書に一致するものがあるかどうかを確認する必要があります。最初のワイルドカードはVendor番号、2番目のワイルドカードは請求書 不一致出力をテキストファイルにしたい。PowerShellは、テキストファイルを1行ずつ読み込み、見つからないファイルをフォルダ内に見つけます。

$Location = "I:\\Vendors\*\Invoices\*" 
$txt = "C:\\Users\sbagford.RECOEQUIP\Desktop\AP.txt" 
$Output ="I:\\Vendors\Missing\Missing.txt" 
foreach ($line in Get-Content $txt) { 
if (-not($line -match $location)){$line} 
} 
set-content $Output -value $Line 

txtまたはcsvファイルのサンプルデータ。上記のデータで

kvendnum wapinvoice 
000953 90269211 
000953 90238674 
001072 11012016 
002317 448668 
002419 06123711 
002419 06137343 
002419 06134382 
002419 759208 
002419 753087 
002419 753069 
002419 762614 
003138 N6009348 
003138 N6009552 
003138 N6009569 
003138 N6009612 
003182 770016 
003182 768995 
003182 06133429 

唯一の試合は二行目にあります:000953 90238674 と6行:002419 06137343

+6

を次のように正規表現が破壊されます。ワイルドカードを使用した場合は、ワイルドカードを使用します。 – mjolinor

答えて

0

テストされていないが、ここで私はそれにアプローチしたい方法は次のとおりです。

$Location = "I:\\Vendors\\.+\\Invoices\\.+" 
$txt = "C:\\Users\sbagford.RECOEQUIP\Desktop\AP.txt" 
$Output ="I:\\Vendors\Missing\Missing.txt" 
select-string -path $txt -pattern $Location -notMatch | 
    set-content $Output 

ファイルを1行ずつ選ぶ必要はありません。 PowerShellはselect-stringを使用してこれを行うことができます。 -notMatchパラメータは検索を単に反転し、パターンに一致しない行を送信します。

select-stringは、検索条件を満たす行を含むmatchinfoオブジェクトのストリームを送信します。これらのオブジェクトには、実際には一致する行だけの情報が含まれていますが、幸いPowerShellはスマートで、関連する項目をset-contentに送信する方法を知っています。

正規表現は正しく動作するようにすることはできますが、このような作業を行う場合は頭を下げる価値があります。

EDIT

$Location = "I:\Vendors\{0}\Invoices\{1}.pdf" 
$txt = "C:\\Users\sbagford.RECOEQUIP\Desktop\AP.txt" 
$Output = "I:\Vendors\Missing\Missing.txt" 

get-content -path $txt | 
    % { 

     # extract fields from the line 
     $lineItems = $_ -split " " 

     # construct path based on fields from the line 
     $testPath = $Location -f $lineItems[0], $lineItems[1] 

     # for debugging purposes 
     write-host ("Line:'{0}' Path:'{1}'" -f $_, $testPath) 

     # test for existence of the path; ignore errors 
     if (-not (get-item -path $testPath -ErrorAction SilentlyContinue)) { 
      # path does not exist, so write the line to pipeline 
      write-output $_ 

     } 

    } | 
    Set-Content -Path $Output 

は、私たちは後にすべてのファイルを介してライン・バイ・ラインを選択する必要がありますね。これを行うもっと慣用的な方法があれば、それは私を見逃す。

上記のコードは、入力ファイルで一貫した書式を前提としており、-splitを使用して行を配列に分割します。

EDIT - バージョン3

$Location = "I:\Vendors\{0}\Invoices\{1}.pdf" 
$txt = "C:\\Users\sbagford.RECOEQUIP\Desktop\AP.txt" 
$Output = "I:\Vendors\Missing\Missing.txt" 

get-content -path $txt | 
    select-string "(\S+)\s+(\S+)" | 
    %{ 

     # pull vendor and invoice numbers from matchinfo  
     $vendor = $_.matches[0].groups[1] 
     $invoice = $_.matches[0].groups[2] 

     # construct path 
     $testPath = $Location -f $vendor, $invoice 

     # for debugging purposes 
     write-host ("Line:'{0}' Path:'{1}'" -f $_.line, $testPath) 

     # test for existence of the path; ignore errors 
     if (-not (get-item -path $testPath -ErrorAction SilentlyContinue)) { 
      # path does not exist, so write the line to pipeline 
      write-output $_ 
     } 

    } | 
    Set-Content -Path $Output 

-split " "が、それはコマンドライン上でどのように動作するかを実行しているスクリプトで異なる挙動ようでした。奇妙な。とにかく、このバージョンでは正規表現を使って入力行を解析します。元の投稿のサンプルデータと比較してテストしたところ、うまくいくように見えました。

あなたは正規表現を期待している-match演算子とワイルドカードの構文を使用している

( Start the first matching group 
\S+ Greedily match one or more non-white-space characters 
)  End the first matching group 
\s+ Greedily match one or more white-space characters 
( Start the second matching group 
\S+ Greedily match one or more non-white-space characters 
)  End the second matching groups 
+0

これを破棄していただきありがとうございます、非常に有益です。各行を読み込んで$ Outputパスに出力していますが、一致していない項目または欠落している項目だけを出力しているわけではありません。 $ txtからすべての行を出力に書き出します。 –

+0

私は$ txtファイルからVendor列を削除し、Invoice列のみを保持しました。 $ txtから一致しない行だけを出力しています。これは、2つの異なるベンダーのもとで請求書が重複している場合を除き、正常に動作します。ベンダーと請求書の両方を検証するための提案はありますか?また、私は+を探しましたが、それが何をしているのかまだ分かりません。もっと明確にしてくれますか? –

+0

私はそれが両方で一致していないが、それは何も出力していないとの問題を解決しようと試みてきました。見てください。 –

関連する問題