pythonを使用してc ++ソースコードの行を解析しようとしています。興味があるのはincludeディレクティブだけです。
#include "header.hpp"
私はそれが柔軟で、まだ次のような貧弱なコーディングスタイルで動作することを望んでいます。
# include"header.hpp"
#の前後の行を読み、空白を削除できるようになりました。ただし、天候に関係なくスペース、引用符、タブ、山括弧などの非アルファ文字に遭遇するまで文字列を読み取ることで、それがどのディレクティブかを見つける必要があります。
だから基本的に私の質問は:非アルファに遭遇するまでアルファで始まる文字列をどのように分割できますか?
私は正規表現でこれを行うことができるかもしれないと思いますが、私が欲しいもののように見えるドキュメントで何も見つかりませんでした。
また、引用符または山かっこで囲まれたファイル名をプラスする方法について誰かがアドバイスを持っている場合も同様です。
あなたは正規表現でそれを行うことができます。ただし、単純な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"')
正規表現を使用する本能は正しいです。
import re
re.split('[^a-zA-Z]', string_to_split)
[^a-zA-Z]
の部分は「アルファベット文字ではない」という意味です。
私の意見では他の人が言及している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']
正規表現を使用できます。 \W
トークンは、すべての非Word文字に一致します(これは、非英数字とほぼ同じです)。単語の文字はA-Z
、a-z
、0-9
、_
。アンダースコアも一致させたい場合は、[\W_]
。
>>> import re
>>> line = '# include"header.hpp" '
>>> m = re.match(r'^\s*#\s*include\W+([\w\.]+)\W*$', line)
>>> m.group(1)
'header.hpp'
import re
s = 'foo bar- blah/hm.lala'
print(re.findall(r"\w+",s))
出力:['foo'、 'bar'、 'blah'、 'hm'、 'lala']
正確ではありませんが、このようなほとんどの解析ヘッダーディレクティブ
(?m)^\h*#\h*include\h*["<](\w[\w.]*)\h*[">]
(?m)は複数行モード、\ hは水平方向の空白(別名[^\S\r\n])です。
これは機能します:
import re
test_str = ' # include "header.hpp"'
match = re.match(r'\s*#\s*include\s*("[\w.]*")', test_str)
if match:
print match.group(1)