2013-08-27 2 views
5

質問パート1パイソン:re.compileとre.sub

私は、このファイルF1ました:

<something @37> 
<name>George Washington</name> 
<a23c>Joe Taylor</a23c> 
</something @37> 

をし、私はそれがこのF1のように見えるということをre.compileたい:(

George Washington Joe Taylor 

)スペースで、私はこのコードを試してみましたが、それはちょっと、すべて削除します。

import re 
file = open('f1.txt') 
fixed = open('fnew.txt','w') 
text = file.read() 

match = re.compile('<.*>') 
for unwanted in text: 
    fixed_doc = match.sub(r' ',text) 

fixed.write(fixed_doc) 

私の推測はre.compile行ですが、どうすればよいか分かりません。私はサードパーティの拡張機能を使うべきではない。何か案は?

from collections import Counter 

def test(): 
    with open('f1.txt') as f: 
     contentsI = f.read() 
    with open('f2.txt') as f: 
     contentsO = f.read() 

    tokensI = Counter(value for value in contentsI.split() 
         if value not in []) 
    tokensO = Counter(value for value in contentsO.split() 
         if value not in []) 
    return not (tokensI - tokensO) and not (set(tokensO) - set(tokensI)) 

re.compileを実現することが可能である:


質問パート2

は私がアルフェから、このコードを持って2つのファイルを比較に関する別の質問がありましたそして、 '[]'セクションにないifの値をre.subにしますか?

+0

こんにちは。最初の問題は、タグのように見えるものをすべて削除するか、実際にマークアップ言語の要素を定義するタグですか?私は正しい意味で「要素」という単語を使用します。つまり、「開始タグ+要素の内容+終了タグ」を意味します。 - また、ファイルfの内容を公開しているので、そこに改行が入っています。あなたが望む結果として示しているのは、改行がもうない文字列です。それは本当にあなたが望んでいるのか、構造化を線で維持したいと思いますか? – eyquem

+0

[]にはない値の場合はどうしますか?現在のところ、ボイドリストには何もないので意味がありません。あなたはファイルの比較として何をしたいですか?非常に明確ではありません – eyquem

答えて

13

私はあなたのコードで何が起こるかを説明します:

import re 
file = open('f1.txt') 
fixed = open('fnew.txt','w') 
text = file.read() 

match = re.compile('<.*>') 
for unwanted in text: 
    fixed_doc = match.sub(r' ',text) 

fixed.write(fixed_doc) 

命令text = file.read()text名前付きの型文字列の対象テキストを作成します。
私は太字の文字テキストをOBJECTで表現し、textでこのオブジェクトの名前== IDENTIFIERを表すことに注意してください。
命令for unwanted in text:の結果として、テキストオブジェクトによって参照される各文字に識別子unwantedが連続して割り当てられます。

また、re.compile('<.*>')は(私はpersonnalyコンパイルを呼び出す)タイプRegexObjectのオブジェクト正規表現又は単に正規表現<.*>あるのみ正規表現パターン)を作成します。
matchというコンパイル済みの正規表現オブジェクトを割り当てます。matchはすでに一般的な正規表現オブジェクトのメソッドの名前であり、特にあなたが作成したメソッドの名前であるため、非常に悪いことです。match.matchエラー。
matchモジュールの機能の名前です。
あなたの特定のニーズにこの名前を使用すると、非常に混乱します。あなたはそれを避けなければなりません。

ファイルf1のファイルハンドラの名前としてfileを使用した場合、同じ欠陥があります。 fileはすでにその言語で使用されている識別子なので、それを避けなければなりません。

今、この悪い名前の試合オブジェクトが定義され、命令fixed_doc = match.sub(r' ',text)は、交換r' 'テキストに正規表現一致で見つかったすべての出現箇所を置き換えます。
' 'の代わりにr' 'と書くのは完全に余計です。' 'には絶対にエスケープする必要がないため、正規表現の問題で文字列を書く必要があるたびに生の文字列を書くことは、心配している人々の流行です。そのため、ドット記号「欲張っ<、それが改行文字である場合を除き、>との間に位置するすべての文字を食べる」を意味するそのパターン<.+>

は、出現箇所は試合によってテキストにcatched各ラインまでです最後は>です。
unwantedという名前はこの命令には表示されないため、テキストの各文字に対して順番に実行される操作と同じです。つまり、興味深いものはありません。
プログラムの実行を分析するには、コードにいくつかの印刷指示を入れて、何が起こるかを理解する必要があります。たとえば、print repr(fixed_doc)を実行すると、これを繰り返し印刷すると表示されます:' \n \n \n '。私が言ったように、何も面白くない。

コードにもう1つのデフォルトがあります。ファイルを開いても、それらをシャットダウンしません。ファイルを閉じることは必須です。そうでなければ、この必要性を理解する前に私が個人的にいくつかのコードで見たような奇妙な現象が起こる可能性があります。一部の人々はそれが義務ではないふりをしているが、それは間違っている。
ところで、ファイルを開いたり閉じたりする方が良い方法は、withステートメントを使用することです。あなたは心配することなくすべての仕事をします。

だから、今私はあなたの最初の問題のためのコードを提案することができ、次のよう

import re 

def ripl(mat=None,li = []): 
    if mat==None: 
     li[:] = [] 
     return 
    if mat.group(1): 
     li.append(mat.span(2)) 
     return '' 
    elif mat.span() in li: 
     return '' 
    else: 
     return mat.group() 

r = re.compile('</[^>]+>' 
       '|' 
       '<([^>]+)>(?=.*?(</\\1>))', 
       re.DOTALL) 

text = '''<something @37> 
<name>George <wxc>Washington</name> 
<a23c>Joe </zazaza>Taylor</a23c> 
</something @37>''' 
print '1------------------------------------1' 
print text 
print '2------------------------------------2' 
ripl() 
print r.sub(ripl,text) 
print '3------------------------------------3' 

結果

1------------------------------------1 
<something @37> 
<name>George <wxc>Washington</name> 
<a23c>Joe </zazaza>Taylor</a23c> 
</something @37> 
2------------------------------------2 

George <wxc>Washington 
Joe </zazaza>Taylor 

3------------------------------------3 

原理は次のとおりです。

正規表現は、タグを検出すると、
- 終了タグの場合は と一致します。開始タグの場合は、対応する終了タグがどこかにある場合にのみ一致しますさらにテキスト
正規表現のメソッドrは、置換を実行するために関数ripl()を呼び出します。
一致が開始タグ(対応する終了タグによってテキストのどこかに続く、正規表現の構築によって必要な場合)の場合、ripl()''を返します。
一致が終了タグである場合、ripl()は、この終了タグが以前に検出されたテキストのみが前の開始タグの対応する終了タグである場合のみ、''を返します。これは、開始タグが検出されて一致するたびに、対応する終了タグのスパンのスパンをリストに記録することによって可能になる。

録画リスト、それは微妙だからは、(、undertsandするデフォルト引数のfunctionningを参照してください、それは常に機能ripl()の各呼び出しで使用されているのと同じリストだという順番でデフォルトの引数として定義されています)。
デフォルトの引数を受け取るパラメータとしてliを定義した結果、リストオブジェクトは、いくつかのテキストを連続して分析する場合にいくつかのテキストを分析するときに記録されたすべてのスパンを保持します。リストliが過去のテキストマッチの範囲を保持するのを避けるには、リストを空にする必要があります。私は最初のパラメータは、正規表現のsub()メソッドでそれを使用する前に引数なしでripl()を呼び出すことができるデフォルトの引数None:で定義されるように関数を書いた。
次に、それを使用する前にripl()と書く必要があります。

あなたは、あなたの質問に示した正確な結果を得るために、テキストの改行を削除したい場合は、コードがに変更する必要があります。

import re 

def ripl(mat=None,li = []): 
    if mat==None: 
     li[:] = [] 
     return 
    if mat.group(1): 
     return '' 
    elif mat.group(2): 
     li.append(mat.span(3)) 
     return '' 
    elif mat.span() in li: 
     return '' 
    else: 
     return mat.group() 


r = re.compile('(*\n *)' 
       '|' 
       '</[^>]+>' 
       '|' 
       '<([^>]+)>(?=.*?(</\\2>)) *', 
       re.DOTALL) 

text = '''<something @37> 
<name>George <wxc>Washington</name> 
<a23c>Joe </zazaza>Taylor</a23c> 
</something @37>''' 
print '1------------------------------------1' 
print text 
print '2------------------------------------2' 
ripl() 
print r.sub(ripl,text) 
print '3------------------------------------3' 

結果

1------------------------------------1 
<something @37> 
<name>George <wxc>Washington</name> 
<a23c>Joe </zazaza>Taylor</a23c> 
</something @37> 
2------------------------------------2 
George <wxc>WashingtonJoe </zazaza>Taylor 
3------------------------------------3 
+0

@Duboeでコードを書いてください。私の答えを見てください。私が使用している置換文字は空白ではなく '' '' ''であり、 – eyquem

1

あなたは簡単にこれを行うには美しいスープを使用することができます。

from bs4 import BeautifulSoup 
file = open('f1.txt') 
fixed = open('fnew.txt','w') 

#now for some soup 

soup = BeautifulSoup(file) 

fixed.write(str(soup.get_text()).replace('\n',' ')) 

上記ラインの出力は次のようになります。

George Washington Joe Taylor 

(Atleastのこれはあなたが私を与えたサンプルで動作します)

申し訳ありませんが、私はパート2、幸運を理解していません!

+0

私は既に含まれていない拡張機能を使用することはできませんが、かなりいいです:/ /しかし、私は将来のいくつかのプロジェクトでそれを使うかもしれません:) – dustinboettcher

0

最初の部分は欠落していました。「?」

match = re.compile('<.*?>') 

です。


いずれにしても、第2の質問についてはまだ分かりません。 :/

+0

これはあまりにも単純な解決策です。たとえば、 '' text = 'Atlantic <---これは海です。 << >> \ nBat <---これは動物です。*それを削除してください。 '' 're.sub( '<.+?>'、 ''、text)' 'の結果は' 'Atlantic >>です\ nBat < ---これは動物です*それを取り除く "''。そのようなケースを避けるために私は答えを – eyquem

0

パート1では、次のコードスニペットを試してください。 - しかし、私の推測では、あなたがしたいということです

私はあなたが求めているものとは完全に明確ではない午前:パート2について萌え月

import re 
import os 
def main(): 
    f = open('sample_file.txt') 
    fixed = open('fnew.txt','w') 



    #pattern = re.compile(r'(?P<start_tag>\<.+?\>)(?P<content>.*?)(?P<end_tag>\</.+?\>)') 
    pattern = re.compile(r'(?P<start><.+?>)(?P<content>.*?)(</.+?>)') 
    output_text = [] 
    for text in f: 
     match = pattern.match(text) 
     if match is not None: 
      output_text.append(match.group('content')) 

    fixed_content = ' '.join(output_text) 


    fixed.write(fixed_content) 
    f.close() 
    fixed.close() 

if __name__ == '__main__': 
    main() 

により示唆されるようにしかしbeautifulsoupのようなライブラリを使用することを検討してくださいif re.sub(value) not in []のようなものです。ただし、Counterインスタンスを初期化する前にre.compileに一度だけ電話する必要があります。あなたの質問の第2部分を明確にすればよいでしょう。

実際には、組み込みPython diffモジュールを使用して、2つのファイルの違いを見つけることをお勧めします。diffロジックは十分にテストされて広く使われており、偽の改行、タブ、およびスペース文字の存在に起因する論理的またはプログラム的なエラーに対して脆弱ではないため、独自のdiffアルゴリズムを使用するよりも優れた方法です。