2

次のように、特定の値を含むすべてのセクション名を一致させる方法はありますか。

section aaa:
   some values
   value 5
section bbb:
   more values
   value 6
section ccc:
   some values
   value 5
section ddd:
   more values
   value 6

例えば:

section (.*?):.*?value 6  (DOTALL|MULTILINE)

の代わりにaaa,に一致します。cccbbbddd

と一致させる方法はありbbbますdddか?

ありがとう

更新: 値の行にコロンが含まれていない、またはスペースで始まっていないという前提に基づいた (機能する) ソリューションがあります。ただしvalue 6、値にコロンが含まれている場合やインデントされていない場合でも、一致してそれに先行する最も近いセクションを取得する方法はありますか?

nhahtdh の回答: 正規表現で逆方向に検索しません。後読みがあります (この場合、可変幅の後読みが必要になります) が、非常に非効率的であり、Python の既定の re モジュールはどの形式の後読みもサポートしていません。

私の結論:これは、上記の仮定を使用して純粋な正規表現を使用するか、(私の好み) drawk によって提案された正規表現と python を組み合わせたアプローチを使用することで実行できます (これにはいくつかの仮定があります。つまり、そのセクションには が含まれている必要がありますvalue) 。

更新2:これが私が最終的に得たものです。上記の制限なしで動作するようです。値に で始まる行を含めることはできないという前提がありますsection .*:。セクションを次のセクションまで一致させますが、((?=...)構文を使用して)それを含めません\Z。また、文字列の終わりである最後のセクションと一致させるために。

for m in re.finditer(r'^section (.*?):(.*?)(?=(^section .*:)|\Z)', str1, re.MULTILINE | re.DOTALL):
    section = m.group(1)
    values = m.group(2)    
    if "value 6" in values:
        print section
4

4 に答える 4

2

最後のセクションだけが必要な場合:

print re.findall(r'^section (\w+):',tgt,flags=re.MULTILINE)[-1]

あなたの編集で、これはそれを行います:

import re

tgt='''\
section aaa:
   some values
   value 5
section bbb:
   more values
   value 6
section ccc:
   some values
   value 5
section ddd:
   more values
   value 6'''

pat=re.compile(r'^section (\w+):.*?value (\d+)',flags=re.MULTILINE|re.DOTALL)

print [(m.group(1),m.start(),m.end()) 
          for m in pat.finditer(tgt)
          if m.group(2)=='6']

版画:

[('bbb', 39, 77), ('ddd', 117, 155)]

編集

見てください、コロンもインデントもありません:

再輸入

tgt='''\
section aaa:
   some values
   value 5
section bbb
   more values
value 6
section ccc:
   some values
   value 5
section ddd:
   more values
   value 6'''

pat=re.compile(r'^section (\w+).*?^\s*value (\d+)',flags=re.MULTILINE|re.DOTALL)

print [(m.group(1),m.start(),m.end()) 
          for m in pat.finditer(tgt)
          if m.group(2)=='6']

同じ出力

編集 2

一致する「値」セクションを持たない可能性のあるセクションを除外することが重要な場合は、2 つの正規表現を使用して、最初の正規表現を前方参照で使用します。

import re

tgt='''\
section aaa:
   some values

section bbb:
   more values
   value 6
section ccc:
   some values
   value 5
section ddd:
   more values
   value 6'''

pat1=re.compile(r'^section (\w+):(.*?)(?=section|\Z)',flags=re.MULTILINE|re.DOTALL)
pat2=re.compile(r'^\s*value (\d+)',flags=re.MULTILINE)

for m in pat1.finditer(tgt):
    m2=re.search(r'^\s*value (\d+)',m.group(2),flags=re.MULTILINE)
    if m2 and m2.group(1)=='6':
        print m.group(1)

プリントbbbddd

于 2013-05-25T19:22:20.463 に答える
2

セクション名に が含まれておらず、有効なセクションを行の先頭で:宣言する必要があると仮定すると、このソリューションは、指定された値を持つセクションのすべての名前を検索します。正規表現はオプションでコンパイルする必要があります。section MULTILINE

^section ([^:\n]+):.*\n( +.*\n)*( +value 6\b)

説明:

  • ^section ([^:\n]+):.*\nで始まる行を検索しsection 、その後にセクション名 (:または改行文字を含まないと想定)、その後に:. 残り.*\nは行の残りと一致しsectionます。
  • ( +.*\n)*インデントのスペースが 1 つ以上ある行に一致します。次のセクションに「こぼれる」ことがないようにします。
  • ( +value 6\b)目的の値を含む行 (の一部) に一致します。の後に別の数字 (63)、アルファベット (6a)、またはアンダースコア (6_) が続かない\bことを確認します。6

このソリューションは、some valuesコロンが含まれていても機能します:

デモ

flag またはflag を使用すると、 の効果\bが異なる場合があることに注意してください。LOCALEUNICODE

于 2013-05-25T19:37:39.210 に答える