2

私はpythonが初めてで、その方法にこだわっています。エラー メッセージが含まれる約 4GB の非常に大きなテキスト ファイルがあります。テキスト ファイルの各メッセージ行は 1 つのメッセージを表します。複数の列を除外し、スペース文字を | に置き換える必要があります。例:

input:
83b14af0-949b-71e0-18d5-0ad781020000 40ba8352-8dd2-71dc-12b8-0ad781020000 1 -1407714483 20 COLG-GRA-617-RD1.oss 1 181895426 12 oss-ap-1.oss 0 0 48 0 0 0 1307845644 1307845647 0 2 12 0 0 0  0 0 12 0 0 0  0 0 1307845918 3 OpC 6 opcecm 9 SNMPTraps 8 IBB_COLG 4 ATM0 0  0  0  69 Cisco Agent Interface Up (linkUp Trap) on interface ATM0 --Sev Normal 372 Generic: 3; Specific: 0; Enterprise: .1.3.6.1.4.1.9.1.569;
output:
83b14af0-949b-71e0-18d5-0ad781020000 | 40ba8352-8dd2-71dc-12b8-0ad781020000 | COLG-GRA-617-RD1.oss | 1307845644 | 1307845647 |1307845918 | Cisco Agent Interface Up (linkUp Trap) on interface ATM0 | Normal 372 | Generic: 3 | Specific: 0 | Enterprise: .1.3.6.1.4.1.9.1.569

本当に私は助けに感謝します

ありがとうございました

4

3 に答える 3

2

入力ファイルの形式が面倒です。入力を空白で分割することもできますが、キャプチャするフィールドの一部には空白が含まれている必要があります。入力を列番号で分割することもできますが、すべての文字列が常に同じ長さであるかどうかはわかりません。数字の桁数が異なる可能性が高いようです。したがって、最善の解決策には正規表現を使用する必要があります。

この行全体を解析するための単一の正規表現は、記述して理解するのが非常に面倒です。しかし、短いパターンからパターンを構築することはできます。結果は分かりやすいと思います。また、ファイル形式が変わったり、キャプチャしたいフィールドが変わったりした場合は、これを簡単に変更できると思います。

*短いパターンを繰り返すために、Python の「文字列繰り​​返し」演算子 を使用していることに注意してください。認識してキャプチャしたい単語が 2 つある場合はc*2、キャプチャ パターンを 2 回繰り返すことができます。

目的の出力の例では、余分な空白がありました。空白が入らないようにパターンを書きましたが、実際に空白が必要な場合は、パターンを自由に編集できます。

正規表現についてよくわからない場合は、Pythonreモジュールのドキュメントを読む必要があります。簡単に言えば、括弧で囲まれたパターンの部分がキャプチャされ、他の部分は一致しますがキャプチャされません。 \s空白に\S一致し、非空白に一致します。 +パターン内の は「1 以上」を*意味し、「0 以上」を意味します。 ^パターンの先頭と$末尾にそれぞれ一致します。

import re

# Define patterns we want to recognize.

c = r'(\S+)\s+'  # a word we want to capture
s = r'\S+\s+'  # a word we want to skip
mesg = r'(\S.*\S)\s+--Sev\s+'  # mesg to capture; terminated by string '--Sev'
w2 = r'(\S+\s+\S+)\s+'  # two words separated by some white space
w2semi = r'(\S+\s+\S+)\s*;\s+'  # two words terminated by a semicolon
tail = r'(.*\S)\s*;'

# Join together the above patterns to make one giant pattern that parses
# the input.
s_pat = ( r'^\s*' + 
    c*2 + s*3 + c*1 + s*10 + c*2 + s*14 + c*1 + s*14 +
    mesg + w2 + w2semi*2 + tail +
    r'\s*$')

# Pre-compile the pattern for speed.
pat = re.compile(s_pat)

# Test string and the expected output result.
s_input = "83b14af0-949b-71e0-18d5-0ad781020000 40ba8352-8dd2-71dc-12b8-0ad781020000 1 -1407714483 20 COLG-GRA-617-RD1.oss 1 181895426 12 oss-ap-1.oss 0 0 48 0 0 0 1307845644 1307845647 0 2 12 0 0 0  0 0 12 0 0 0  0 0 1307845918 3 OpC 6 opcecm 9 SNMPTraps 8 IBB_COLG 4 ATM0 0  0  0  69 Cisco Agent Interface Up (linkUp Trap) on interface ATM0 --Sev Normal 372 Generic: 3; Specific: 0; Enterprise: .1.3.6.1.4.1.9.1.569;"
s_correct = "83b14af0-949b-71e0-18d5-0ad781020000|40ba8352-8dd2-71dc-12b8-0ad781020000|COLG-GRA-617-RD1.oss|1307845644|1307845647|1307845918|Cisco Agent Interface Up (linkUp Trap) on interface ATM0|Normal 372|Generic: 3|Specific: 0|Enterprise: .1.3.6.1.4.1.9.1.569"

# re.match() returns a "match group"
m = re.match(pat, s_input)
# m.groups() returns sequence of captured strings; join with '|'
s_output = '|'.join(m.groups())

# sanity check
if s_correct == s_output:
    print "excellent"
else:
    print "bogus"

# excellent.

パターンを作成し、テストし、デバッグしたので、実際にファイルを処理するプログラムを作成するのは非常に簡単です。

# use the pattern defined above, named "pat"
with open(input_file, "r") as f_in, open(output_file, "w") as f_out:
    for line_num, line in enumerate(f_in, 1):
        try:
            m = re.match(pat, line)
            s_output = '|'.join(m.groups())
            f_out.write(s_output + '\n')
        except Exception:
            print("unable to parse line %d: %s" % (line_num, line)

これにより、一度に 1 行ずつファイルが読み取られ、その行が処理され、処理された行が出力ファイルに書き込まれます。

with1 行で複数のステートメントを使用していることに注意してください。これは最近の Python では動作しますが、2.5 または 3.0 では動作しません。

于 2012-04-09T07:54:04.423 に答える
1

replace()読み込んだ行には、文字列の組み込みメソッドを使用します。文字列メソッドのリストについては、http://docs.python.org/library/stdtypes.html#string-methodsを参照してください。

new_string = my_string.replace(' ', ' | ')

「列」も削除する必要がある場合は、最初に文字列を分割し、「スライス」で列を削除してから、スプリッターでリストを結合すると、運が良くなります。

cols = my_string.split(' ')
cols = cols[:2] + cols[4:8] + cols[11:]  #Just making up some arbitrary removed columns
new_string = ' | '.join(cols)

これは、入力が常にスペースで区切られ、データにスペースが含まれていないことを前提としていることに注意してください。入力データがより複雑な場合、分割コードはもう少し興味深いものになります。

于 2012-04-09T06:41:29.140 に答える
0

Linux を使用している場合は、sed コマンドを使用して簡単に文字を置き換えることができます。ファイルが大きすぎるため、Python で 1 行ずつ読み取るよりも高速です。

sed -i 's/pattern/|/g' inputfile

上記のコマンドは、すべてのパターン文字列を | に置き換えます。

于 2012-04-09T08:26:42.760 に答える