3

文字列内の有効な Python 整数リテラルに一致する正規表現は何ですか? oやのようなすべての余分なものをサポートする必要lがありますが、フロートや数値を含む変数には一致しません。私は Python の を使用してreいるので、それでサポートされている構文はすべて問題ありません。

編集:これが私の動機です(明らかにそれは非常に重要です)。http://code.google.com/p/sympy/issues/detail?id=3182を修正しようとしています。私がやりたいのは、自動的に int/int ( のような1/2) をRational(int, int), ( のような ) に変換する IPython 用のフックを作成することです。その理由は、 Python 型の Python 型であるため、有理数として登録Rational(1, 2)することができないためです。 SymPy、これは非常に厄介な場合があります. 1/2__div__x**(1/2)x**0x**0.5__future__x**Rational(1, 2)

私の解決策は、入力内のすべての整数リテラルを自動的に整数 (Rational除算を行う SymPy のカスタム整数クラス) でラップするフックを IPython に追加することです。isympyこれにより、必要な人のために、この点で SymPy を従来のコンピューター代数システムのように動作させるオプションを追加できます。これが、任意の Python 式内のすべてのリテラルに一致させる必要がある理由を説明してくれることを願っています。これが、名前に数字が含まれる float リテラルや変数に一致させる必要がない理由です。

また、みんなが私が試したことに非常に興味を持っているので、ここで: あきらめる前に (正規表現は難しい)。フロートリテラルの最初の部分をキャッチしないように遊んでい(?!\.)ましたが、これはうまくいかないようでした(誰かが理由を教えてくれたら興味があります。例は ですre.sub(r"(\d*(?!\.))", r"S\(\1\)", "12.1"))。

EDIT 2:これを と組み合わせて使用​​ する予定なので、re.sub使用できるように、回答の全体を括弧で囲むこともできます\1:)

4

6 に答える 6

5

整数リテラルの定義は次のとおりです(3.xでは、2.xではわずかに異なります)。

integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"+
nonzerodigit   ::=  "1"..."9"
digit          ::=  "0"..."9"
octinteger     ::=  "0" ("o" | "O") octdigit+
hexinteger     ::=  "0" ("x" | "X") hexdigit+
bininteger     ::=  "0" ("b" | "B") bindigit+
octdigit       ::=  "0"..."7"
hexdigit       ::=  digit | "a"..."f" | "A"..."F"
bindigit       ::=  "0" | "1"

だから、このようなもの:

[1-9]\d*|0|0[oO][0-7]+|0[xX][\da-fA-F]+|0[bB][01]+

「l」をサポートしたいということからすると、実際には2.xの定義が必要だと思います。

longinteger    ::=  integer ("l" | "L")
integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"
octinteger     ::=  "0" ("o" | "O") octdigit+ | "0" octdigit+
hexinteger     ::=  "0" ("x" | "X") hexdigit+
bininteger     ::=  "0" ("b" | "B") bindigit+
nonzerodigit   ::=  "1"..."9"
octdigit       ::=  "0"..."7"
bindigit       ::=  "0" | "1"
hexdigit       ::=  digit | "a"..."f" | "A"..."F"

書くことができます

(?:[1-9]\d+|0|0[oO]?[0-7]+|0[xX][\da-fA-F]+|0[bB][01]+)[lL]?
于 2012-07-31T04:55:14.887 に答える
4

構文については、http://docs.python.org/reference/lexical_analysis.html#integersで説明されています。これを正規表現として表現する1つの方法は次のとおりです。

(0|[1-9][0-9]*|0[oO]?[0-7]+|0[xX][0-9a-fA-F]+|0[bB][01]+)[lL]?

免責事項:これは負の整数をサポートしていません。Pythonでは、の-ようなもの-31は実際には整数リテラルの一部ではなく、別個の演算子であるためです。

于 2012-07-31T04:53:42.230 に答える
4

re を使用するのが正しいとは思えません。Python にはtokenizeastsymbolおよびparserPython コードの解析/処理/操作/書き換えに使用できるモジュールがあります...

>>> s = "33.2 + 6 * 0xFF - 0744"
>>> from StringIO import StringIO
>>> import tokenize
>>> t = list(tokenize.generate_tokens(StringIO(s).readline))
>>> t
[(2, '33.2', (1, 0), (1, 4), '33.2 + 6 * 0xFF - 0744'), (51, '+', (1, 5), (1, 6), '33.2 + 6 * 0xFF - 0744'), (2, '6', (1, 7), (1, 8), '33.2 + 6 * 0xFF - 0744'), (51, '*', (1, 9), (1, 10), '33.2 + 6 * 0xFF - 0744'), (2, '0xFF', (1, 11), (1, 15), '33.2 + 6 * 0xFF - 0744'), (51, '-', (1, 16), (1, 17), '33.2 + 6 * 0xFF - 0744'), (2, '0744', (1, 18), (1, 22), '33.2 + 6 * 0xFF - 0744'), (0, '', (2, 0), (2, 0), '')]
>>> nums = [eval(i[1]) for i in t if i[0] == tokenize.NUMBER]
>>> nums
[33.2, 6, 255, 484]
>>> print map(type, nums)
[<type 'float'>, <type 'int'>, <type 'int'>, <type 'int'>]

http://docs.python.org/library/tokenize.htmlに、float を次のように書き直す例があります。decimal.Decimal

于 2012-07-31T07:58:50.647 に答える
2

両方の「方言」を本当に一致させたい場合は、たとえば 8 進数を使用するなど、あいまいさが生じます (これoは Python 3 で必要です)。ただし、次のように動作するはずです。

r = r"""(?xi) # Verbose, case-insensitive regex
(?<!\.)       # Assert no dot before the number
\b            # Start of number
(?:           # Match one of the following:
 0x[0-9a-f]+| # Hexadecimal number
 0o?[0-7]+|   # Octal number
 0b[01]+|     # Binary number
 0+|          # Zero
 [1-9]\d*     # Other decimal number
)             # End of alternation
L?            # Optional Long integer
\b            # End of number
(?!\.)        # Assert no dot after the number"""
于 2012-07-31T06:19:04.737 に答える
1

このようなもので十分でしょうか?

r = r"""
(?<![\w.])               #Start of string or non-alpha non-decimal point
    0[X][0-9A-F]+L?|     #Hexadecimal
    0[O][0-7]+L?|        #Octal
    0[B][01]+L?|         #Binary
    [1-9]\d*L?           #Decimal/Long Decimal, will not match 0____
(?![\w.])                #End of string or non-alpha non-decimal point
"""

(フラグ付きre.VERBOSE | re.IGNORECASE)

于 2012-07-31T05:27:23.317 に答える
0

これはかなり近づきます:

re.match('^(0[x|o|b])?\d+[L|l]?$', '0o123l')
于 2012-07-31T05:00:41.157 に答える