web-dev-qa-db-ja.com

Python-文字列をアルファベット以外の文字で分割する方法

pythonを使用してc ++ソースコードの行を解析しようとしています。興味があるのはincludeディレクティブだけです。

    #include "header.hpp"

私はそれが柔軟で、まだ次のような貧弱なコーディングスタイルで動作することを望んでいます。

          #   include"header.hpp"  

#の前後の行を読み、空白を削除できるようになりました。ただし、天候に関係なくスペース、引用符、タブ、山括弧などの非アルファ文字に遭遇するまで文字列を読み取ることで、それがどのディレクティブかを見つける必要があります。

だから基本的に私の質問は:非アルファに遭遇するまでアルファで始まる文字列をどのように分割できますか?

私は正規表現でこれを行うことができるかもしれないと思いますが、私が欲しいもののように見えるドキュメントで何も見つかりませんでした。

また、引用符または山かっこで囲まれたファイル名をプラスする方法について誰かがアドバイスを持っている場合も同様です。

11
nickeb96

あなたは正規表現でそれを行うことができます。ただし、単純なwhileループを使用することもできます。

def splitnonalpha(s):
   pos = 1
   while pos < len(s) and s[pos].isalpha():
      pos+=1
   return (s[:pos], s[pos:])

テスト:

>>> splitnonalpha('#include"blah.hpp"')
('#include', '"blah.hpp"')
7
kfx

正規表現を使用する本能は正しいです。

import re
re.split('[^a-zA-Z]', string_to_split)

[^a-zA-Z]の部分は「アルファベット文字ではない」という意味です。

23
nlloyd

私の意見では他の人が言及している2つのオプションはre.splitおよびre.findall

>>> import re
>>> re.split(r'\W+', '#include "header.hpp"')
['', 'include', 'header', 'hpp', '']
>>> re.findall(r'\w+', '#include "header.hpp"')
['include', 'header', 'hpp']

簡単なベンチマーク:

>>> setup = "import re; Word_pattern = re.compile(r'\w+'); sep_pattern = re.compile(r'\W+')"
>>> iterations = 10**6
>>> timeit.timeit("re.findall(r'\w+', '#header foo bar!')", setup=setup, number=iterations)
3.000092029571533
>>> timeit.timeit("Word_pattern.findall('#header foo bar!')", setup=setup, number=iterations)
1.5247418880462646
>>> timeit.timeit("re.split(r'\W+', '#header foo bar!')", setup=setup, number=iterations)
3.786440134048462
>>> timeit.timeit("sep_pattern.split('#header foo bar!')", setup=setup, number=iterations)
2.256173849105835

機能的な違いはre.split空のトークンを保持します。これは通常、トークン化の目的には役立ちませんが、以下はre.findall 解決:

>>> filter(bool, re.split(r'\W+', '#include "header.hpp"'))
['include', 'header', 'hpp']
5
Denis Drescher

正規表現を使用できます。 \Wトークンは、すべての非Word文字に一致します(これは、非英数字とほぼ同じです)。単語の文字はA-Za-z0-9_。アンダースコアも一致させたい場合は、[\W_]

>>> import re
>>> line = '#   include"header.hpp"  ' 
>>> m = re.match(r'^\s*#\s*include\W+([\w\.]+)\W*$', line)
>>> m.group(1)
'header.hpp'
2
Patrick Carroll
import re
s = 'foo bar- blah/hm.lala'
print(re.findall(r"\w+",s))

出力:['foo'、 'bar'、 'blah'、 'hm'、 'lala']

1
Daniyal Syed

正確ではありませんが、このようなほとんどの解析ヘッダーディレクティブ

(?m)^\h*#\h*include\h*["<](\w[\w.]*)\h*[">]

(?m)は複数行モード、\ hは水平方向の空白(別名[^\S\r\n])です。

0
user557597

これは機能します:

import re

test_str = '    #   include "header.hpp"'

match = re.match(r'\s*#\s*include\s*("[\w.]*")', test_str)
if match:
    print match.group(1)
0
Garrett R