複数行の検索と置換


8

検索を実行し、12000行のファイルで置き換えます。

具体的には、のオカレンスがブロックの^ SetFontSize 28後で^Hide次の^Hideorの前に存在する場合は^Show、に変更2818ます。

元のファイルからの抜粋です。

Hide # Gear - Endgame
    ItemLevel >= 77
    Rarity = Magic
    LinkedSockets >= 3
    BaseType "Runic Hatchet"
    SetTextColor 140 190 255 # Magic Item Highlight
    SetFontSize 28

Hide # Gear - Endgame
    ItemLevel >= 77
    Rarity = Magic
    Sockets >= 3
    BaseType "Runic Hatchet"
    SetTextColor 140 190 255 # Magic Item Highlight
    SetFontSize 28

Show # Gear - Endgame
    ItemLevel >= 83
    Rarity = Normal
    Sockets < 3
    BaseType "Tiger Hook"
    SetTextColor 240 240 240 # Normal Item Highlight
    SetBackgroundColor 70 70 70
    SetFontSize 28

いずれかのHideブロックの最終結果は次のようになります。

Hide # Gear - Endgame
    ItemLevel >= 77
    Rarity = Magic
    LinkedSockets >= 3
    BaseType "Runic Hatchet"
    SetTextColor 140 190 255 # Magic Item Highlight
    SetFontSize 18

交換SetFontSize 28するSetFontSize 18が、それはに表示されている場合にのみ^Hideブロック。

私が試した厄介な正規表現は: :%s/^Hide\(.*\)SetFontSize 28$/Hide\1SetFontSize 18/g

しかし、パターンが見つからないと言われました。追加の情報が必要な場合や、リクエストが不明確な場合はお知らせください。


5
すべてのHideブロックにSetFontSize線がありますか(値は何であっても)?もしそうなら、あなたは使うことができます:%s/Hide\_.\{-\}SetFontSize \zs28/18/
muru

2
@muru whatever be the valueは問題を引き起こします。ソリューションは、すべてのHideブロックにSetFontSize行があり、その値が正確28にある場合にのみ機能します。それ以外の場合、28別のブロックまで一致します。
dedowsdi

回答:


2

これを解決する1つの方法は、それを使用:globalして範囲出力を生成することです。

globalコマンドの典型的な使用法は

:[range]g/{pattern}/[cmd]

また,、次の形式で使用することにより、このパターンに単一行の一致ではなく範囲を生成させるオプションもあります。

:[range]g/{first pattern}/,/{second pattern}/[cmd]

これにより、コマンドに適用される範囲が生成されます。

あなたの例えば最初のパターンは、第1マッチングされるだろうHideエントリを第二のパターンのいずれかであるHideShowまたはファイルの終わり(あなたがその最後を隠すケースが欲しいと仮定した場合)。

:g/Hide/,/\(Hide\|Show\|\%$\)/s/SetFontSize 28/SetFontSize 18/

最初の正規表現は単純です/Hide/。2番目の正規表現には、いくつかの興味深い部分が含まれています。

  • \(そして、\)一致する原子の群を作成し、
  • \| OR演算です
  • \%$ ファイルの終わりを表します

範囲を定義したら、通常どおり、パターンと文字列を使用して置換を適用します。

この例で使用されている正規表現は非常に基本的なものであることに注意してください。範囲の最初と最後の識別子が適切な領域をキャプチャしていることを確認する必要があります。


2

あなたの厄介な正規表現は十分に厄介ではなかったようです... :-)

検索セクション

検索は次のように変更する必要があります。

^Hide\(\(\(Show\|Hide\)\@!\_.\)*\)SetFontSize 28

これには、珍しいことがかなり多く、括弧がたくさん含まれています...そこに何があるか見てみましょう:

キャレット(^

キャレットは行の先頭を意味するために使用されます。私たちはすでにこれに精通していると思います。

重要な点として、^はパターンの最初の文字として以外は機能しません。その後、それは逐語的に取られます。式に行頭を含めるには、を使用する必要があります\_^。しかし、私たちの状況では、それは必要ありませんでした。

$およびと同様の現象があります\_$

最初と最後の括弧(\( ... \)

最初と最後の括弧は単独で使用さます\1。つまり、内部に表示されるものをすべて取得し、parameterに設定します。あなたはすでにあなた自身の正規表現でそれを使用したので、あなたもこれに精通していると思います。

括弧の2番目のセット

お気づきかもしれませんが、2番目の括弧のセットの後にアスタリスクが続きます\( ... \)*。これは、何回でも一致するものを探していることを意味します。これはアスタリスクを使用する通常の方法ですので、よく理解しておく必要があります。

括弧の3番目のセット、OR、および \_.

はい、実際には単語の前に3つの括弧がありますShow。この最後のセットは、2つの理由のために必要である:\|そして次@!

OR演算については、すでに熟知しているはずです。

Show\|Hide    or    Hide\|Show

順序はここでは関係ありません。\目の前に必要な|vimの中で作業します。

この式を括弧で囲んで、式の後に何かを付けることができます。ここ@!

\(Show\|Hide\)@!

これはあまり馴染みのないものです。一致しない場合を意味ます。ただし、これを使用するのは簡単ではありませんが、その式の後に、抽出したいものを、その式と一致してはいけないものを使用して追跡する必要があります。これが、\_.そのパターンの背後にある理由です。

\_.手段は何も全く一致しています。とは対照的に.、それは\nキャラクターと一致しません。つまり、Showまたはに一致しない限り、任意の数の行の任意の文字に一致しHideます。

その式の周りの括弧もアスタリスクと同様に重要であることに注意してください。したがって、この全体が実際に機能します。

\(\(Show\|Hide\)@!\_.\)*

別名隣にどんな一致ShowまたはHide(それも一致することに注意してください文字ShowingShowerHideMe、などは、使用することができるはず\<\>、正確に言葉を一致させる必要がある場合。)

注:複数の行を検索する場合は\n、パターンで文字を使用することもできます。ただし、\_.パターンほど用途が広いわけではありません。

SetFontSize 28

ここで、セクションにも含める必要SetFontSize 28があります。あなたがあなたの正規表現で持っていたように。SetFontSize 28そのセクションに何も表示されない場合は、次のセクションで検索を再試行してください。

上記の否定(Showまたは以外の一致Hide)のため、検索は次のセクションにリークせず、混乱するリスクがあります。

交換セクション

交換はあなたが持っていたのとまったく同じです:

.../Hide\1SetFontSize 18/

括弧は検索で使用するため、\1期待どおりに機能します。

完全な検索と置換

結果のパターンは次のようになります。

:%s/^Hide\(\(\(Show\|Hide\)@!\_.\)*\)SetFontSize 28/Hide\1SetFontSize 18/

\(Show\|Hide\)は、可能なすべてのヘッダーを含める必要があります。

出典

改行\_.\{-}を含むすべての文字に一致する正規表現

パターンを含まない行の検索およびその他の役立つ検索@!

Vimドキュメント:パターン\_^


1
()*はあなたの答えの私のバージョンが好きです%s/\v^Hide.*\n(\s+.*\n)*\s*SetFontSize\s+\zs28/16
dedowsdi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.