14

Python Regex を使用して小さな問題に遭遇しました。

これが入力であるとします:

(zyx)bc

私が達成しようとしているのは、括弧の間にあるものを単一の一致として取得し、外側の文字を個別の一致として取得することです。望ましい結果は、次のようになります。

['zyx','b','c']

試合の順番は守らなければなりません。

Python 3.3 でこれを取得しようとしましたが、正しい正規表現を理解できないようです。これまでのところ、私は持っています:

matches = findall(r'\((.*?)\)|\w', '(zyx)bc')

print(matches)次の結果が得られます。

['zyx','','']

私が間違っていることはありますか?

4

5 に答える 5

18

のドキュメントからre.findall:

パターンに 1 つ以上のグループが存在する場合は、グループのリストを返します。パターンに複数のグループがある場合、これはタプルのリストになります。

正規表現が文字列に 3 回一致している間、(.*?)グループは次の 2 つの一致に対して空です。正規表現の残りの半分の出力が必要な場合は、2 番目のグループを追加できます。

>>> re.findall(r'\((.*?)\)|(\w)', '(zyx)bc')
[('zyx', ''), ('', 'b'), ('', 'c')]

または、すべてのグループを削除して、単純な文字列のリストを再度取得することもできます。

>>> re.findall(r'\(.*?\)|\w', '(zyx)bc')
['(zyx)', 'b', 'c']

ただし、括弧を手動で削除する必要があります。

于 2013-01-06T13:00:29.003 に答える
6

他の回答では、必要な結果を得る方法が示されていますが、括弧を手動で削除するという追加の手順があります。正規表現でルックアラウンドを使用する場合は、括弧を手動で削除する必要はありません。

>>> import re
>>> s = '(zyx)bc'
>>> print (re.findall(r'(?<=\()\w+(?=\))|\w', s))
['zyx', 'b', 'c']

説明:

(?<=\() // lookbehind for left parenthesis
\w+     // all characters until:
(?=\))  // lookahead for right parenthesis
|       // OR
\w      // any character
于 2013-01-06T15:01:11.833 に答える
3

を使用して出力を見てみましょうre.DEBUG

branch 
  literal 40 
  subpattern 1 
    min_repeat 0 65535 
      any None 
  literal 41 
or
  in 
    category category_word

ああ、そこには 1 つしかsubpatternありませんが、存在する場合にre.findallのみ s を引き出しsubpatternます!

a = re.findall(r'\((.*?)\)|(.)', '(zyx)bc',re.DEBUG); a
[('zyx', ''), ('', 'b'), ('', 'c')]
branch 
  literal 40 
  subpattern 1 
    min_repeat 0 65535 
      any None 
  literal 41 
or
  subpattern 2 
    any None

より良い。:)

あとは、これを必要な形式にするだけです。

[i[0] if i[0] != '' else i[1] for i in a]
['zyx', 'b', 'c']
于 2013-01-06T13:07:56.927 に答える
2

ドキュメントでは、グループを特別に扱うことが言及されているため、括弧で囲まれたパターンの周りにグループを配置しないでください。すべてを取得できますが、一致したデータから括弧を自分で削除する必要があります。

>>> re.findall(r'\(.+?\)|\w', '(zyx)bc')
['(zyx)', 'b', 'c']

または、より多くのグループを使用してから、結果のタプルを処理して、求める文字列を取得します。

>>> [''.join(t) for t in re.findall(r'\((.+?)\)|(\w)', '(zyx)bc')]
>>> ['zyx', 'b', 'c']
于 2013-01-06T13:02:36.533 に答える
1
In [108]: strs="(zyx)bc"

In [109]: re.findall(r"\(\w+\)|\w",strs)
Out[109]: ['(zyx)', 'b', 'c']

In [110]: [x.strip("()") for x in re.findall(r"\(\w+\)|\w",strs)]
Out[110]: ['zyx', 'b', 'c']
于 2013-01-06T13:05:17.697 に答える