76

sscanf()Pythonに相当するものを探しています。ファイルを解析したいのです/proc/net/*が、CIでは次のようなことができます。

int matches = sscanf(
        buffer,
        "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*X:%*X %*X:%*X %*X %*d %*d %ld %*512s\n",
        local_addr, &local_port, rem_addr, &rem_port, &inode);

最初はを使用することを考えましstr.splitたが、指定された文字では分割されず、sep文字列全体で分割されます。

>>> lines = open("/proc/net/dev").readlines()
>>> for l in lines[2:]:
>>>     cols = l.split(string.whitespace + ":")
>>>     print len(cols)
1

上で説明したように、これは17を返すはずです。

(REではなく)同等のPython sscanf、または私が知らない文字の範囲のいずれかで分割する文字列分割関数が標準ライブラリにありますか?

4

13 に答える 13

90

モジュールもありparseます。

parse()format()(Python 2.6以降の新しい文字列フォーマット関数)の反対になるように設計されています。

>>> from parse import parse
>>> parse('{} fish', '1')
>>> parse('{} fish', '1 fish')
<Result ('1',) {}>
>>> parse('{} fish', '2 fish')
<Result ('2',) {}>
>>> parse('{} fish', 'red fish')
<Result ('red',) {}>
>>> parse('{} fish', 'blue fish')
<Result ('blue',) {}>
于 2012-10-12T04:18:49.763 に答える
69

私が C 気分のときは、通常、scanf のような動作のために zip とリストの内包表記を使用します。このような:

input = '1 3.0 false hello'
(a, b, c, d) = [t(s) for t,s in zip((int,float,strtobool,str),input.split())]
print (a, b, c, d)

より複雑なフォーマット文字列については、正規表現を使用する必要があることに注意してください。

import re
input = '1:3.0 false,hello'
(a, b, c, d) = [t(s) for t,s in zip((int,float,strtobool,str),re.search('^(\d+):([\d.]+) (\w+),(\w+)$',input).groups())]
print (a, b, c, d)

また、変換するすべての型に対して変換関数が必要であることにも注意してください。たとえば、上記では次のようなものを使用しました。

strtobool = lambda s: {'true': True, 'false': False}[s]
于 2012-06-18T14:55:37.410 に答える
36

Python には同等の組み込み関数がありませんsscanf。ほとんどの場合、文字列を直接操作したり、正規表現を使用したり、解析ツールを使用したりして、入力を解析する方がはるかに理にかなっています。

C の翻訳におそらく最も役立つでしょうsscanf。このモジュールのように、人々は を実装しています: http://hkn.eecs.berkeley.edu/~dyoo/python/scanf/

この特定のケースで、複数の分割文字に基づいてデータを分割したい場合re.splitは、本当に適切なツールです。

于 2010-02-01T06:51:50.437 に答える
23

reモジュールを使用して、文字の範囲を分割できます。

>>> import re
>>> r = re.compile('[ \t\n\r:]+')
>>> r.split("abc:def  ghi")
['abc', 'def', 'ghi']
于 2010-02-01T06:41:49.770 に答える
15

名前付きグループreを使用してモジュールで解析できます。部分文字列を実際のデータ型 (例: ) に解析しませんが、文字列を解析する場合は非常に便利です。int

からのこのサンプル行を考えると/proc/net/tcp:

line="   0: 00000000:0203 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 335 1 c1674320 300 0 0 0"

変数を使用して sscanf の例を模倣する例は次のとおりです。

import re
hex_digit_pattern = r"[\dA-Fa-f]"
pat = r"\d+: " + \
      r"(?P<local_addr>HEX+):(?P<local_port>HEX+) " + \
      r"(?P<rem_addr>HEX+):(?P<rem_port>HEX+) " + \
      r"HEX+ HEX+:HEX+ HEX+:HEX+ HEX+ +\d+ +\d+ " + \
      r"(?P<inode>\d+)"
pat = pat.replace("HEX", hex_digit_pattern)

values = re.search(pat, line).groupdict()

import pprint; pprint values
# prints:
# {'inode': '335',
#  'local_addr': '00000000',
#  'local_port': '0203',
#  'rem_addr': '00000000',
#  'rem_port': '0000'}
于 2010-02-01T23:02:59.580 に答える
3

更新: 正規表現モジュールの Python ドキュメントにreは、scanf のシミュレーションに関するセクションが含まれています。これは、上記のどの回答よりも役立つことがわかりました。

https://docs.python.org/2/library/re.html#simulating-scanf

于 2016-12-19T12:38:41.873 に答える
1

「:」をスペースに変えて分割することができます。

>>> f=open("/proc/net/dev")
>>> for line in f:
...     line=line.replace(":"," ").split()
...     print len(line)

正規表現は必要ありません (この場合)

于 2010-02-01T06:50:34.053 に答える
1

基本的なスキャンを実装する ActiveState レシピがあり ます http://code.activestate.com/recipes/502213-simple-scanf-implementation/

于 2010-11-11T17:21:51.983 に答える
0

支持されたoripの答え。re モジュールを使用するのは適切なアドバイスだと思います。Kodos アプリケーションは、Python で複雑な正規表現タスクに取り組むときに役立ちます。

http://kodos.sourceforge.net/home.html

于 2010-08-23T09:46:34.187 に答える
-1

odiak による Python 2 実装があります。

于 2012-10-11T21:28:21.520 に答える
-1

セパレータが「:」の場合、「:」で分割し、文字列で x.strip() を使用して、先頭または末尾の空白を取り除くことができます。int() はスペースを無視します。

于 2010-02-01T11:38:34.423 に答える