PowerShellで6番目のパイプごとに置き換える

PowerShellで6番目のパイプごとに置き換える

すでに質問され回答されている同様の質問をしていることは承知していますが、正規表現と正規表現エンジンがかなり異なるため、必要な回答を推測することができませんでした。エンドポイント間でパイプ区切りですが、メジャー区切りではないハードウェア資産管理ログがあります。ログは次のようになります。

|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3

私がやりたいのは、6 番目ごと|に改行に置き換えて、次のようになることです。

|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1
|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2
|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3

私が得た最も近いものは各エンドポイントを選択しますが、PowerShell を使用してそれをどのように利用すればよいかよくわかりません。

[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*

私は PS の replace コマンドに精通しており、最終結果は次のようなものになるだろうと想像しています。

$hosts = $hosts -replace "<highspeed_low_drag_velcro_snap_regex_here>","\r\n"

前もって感謝します!

答え1

さて、これは実際には少し難しいです。おそらく、正規表現はこの作業に最適なツールではありませんが、実行することは可能です。

-replace "(?<=^((\|[^|]*){5})+)\|","`n|"

詳しく説明してみます:

  • テキストには、マッチそしてあなたが望むセクション交換する伝統的に、正規表現は検索文字列全体を置き換えるので、キャプチャグループ置換出力に複製する検索文字列の一部を指定する。別の方法としては、見回す、ここで私がやったことです。PowerShell (.NET)は、サポートしている数少ない正規表現言語の1つです。可変長後読みなので、私たちは幸運です。
  • セクション(?<=)は後読みです。つまり、=)の間にあるすべてのものは一致しただがしかし交換された.^((\|[^|]*){5})+として使用される状態- このビットが意図した置換の前のテキストと一致する場合にのみ置換が行われます。
  • このセクションは、「行の先頭 ( ) から 5 つの のセットを一致させ、次の までのテキストを一致させる」^((\|[^|]*){5})*[^|]*と要約できます。 ^||
    • 行の先頭は重要です。そうでない場合、行のどこにでも一致する可能性があり、その前に s が^いくつあるかは保証されません。|
    • |は正規表現では特別な意味を持つため、エスケープする必要があります: \|。文字クラス ( []) 内ではエスケープする必要はありません。
    • [^|]*は「次の 」までのテキストを意味します|。より技術的には、「 以外の文字を可能な限り多く」、より技術的には「以外の任意の文字と一致する文字クラスを可能な限り多く|繰り返す」ことを意味します。[^|]|
    • *「前の文字を0回以上、可能な限り繰り返す」という意味です。
    • は、次の までの可能な限り多くの文字に一致する(\|[^|]*)ことを意味します。これは、|||text
    • {5}前のトークンを正確に5回繰り返すことを意味します。これは、前のトークンを5回コピーして貼り付けることとまったく同じです。したがって、これは一致します|text|text|text|text|text
    • ((\|[^|]*){5})+|text|text|text|text|textは、そのグループ全体の 1 回以上の繰り返しです。したがって、5 の倍数の 、 などに一致します。の代わりに|text|text|text|text|text|text|text|text|text|textを使用する理由は、空のグループに一致して最初の を置き換えたくないためです。+*|
    • これにより、全体が lookbehind になり、行の先頭から|5 の倍数だけ後ろに置き換わることになります。|
  • \|これに続いて、置換する実際のテキストとしてa が続き、その前に一致した lookbehind が続きます。
  • あなたの例を取ると|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3、次のようになります:

    |STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1**|**STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2**|**STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3
    

ここで(まだ気づいていないなら)実際にすべての5位 |最初のものを除いて、すべてではない6位しかし、後読みメソッドは「最初のマイナス」の状況をかなりきれいに処理します。


さて、置換文字列です。

  • これは PowerShell なので、 が必要な場合\n、実際には が必要です。PowerShell`nのエスケープ文字は だからです`。これは置換文字列でのみ必要であり、正規表現自体では、そのリテラル シーケンスを正規表現エンジンに渡すために を使用することに注意してください\n
  • |また、各行の先頭に があるため、|新しい行の後にを追加する必要があります。元の行は で終わっていない|ため、行末で置き換えるものはなく、余分な新しい行や末尾の は発生しません|

より伝統的なキャプチャ グループ メソッドを好む場合:

-replace "((?:[^|]+\|){4}[^|]+)\|","`$1`n|"

これがどのように機能するかを理解することは、読者の課題として残されています ;) ヒント:$1バック参照はエスケープする必要があります ( を使用`)。そうしないと、PowerShell はそれをシェル変数として解釈します。

関連情報