4

jascii/shift-jis と ASCII テキストが混在するテキスト ファイルがあります。私は使用pyparsingしていますが、そのような文字列をトークン化できません。

コード例を次に示します。

from pyparsing import *

subrange = r"[\0x%x40-\0x%x7e\0x%x80-\0x%xFC]"
shiftJisChars = u''.join(srange(subrange % (i,i,i,i)) for i in range(0x81,0x9f+1) + range(0xe0,0xfc+1))
jasciistring = Word(shiftJisChars)

jasciistring.parseString(open('shiftjis.txt').read())

私は得る:

トレースバック (最新の呼び出しが最後):
  ファイル「test.py」の 7 行目
    jasciistring.parseString(open('shiftjis.txt').read())
  ファイル「C:\python\lib\site-packages\pyparsing.py」、行 1100、parseString
    exc pyparsing.ParseException を上げる

これは、テキスト ファイルの内容です。

"‚s‚ˆ‚‰"@‚‰‚"@‚@‚"‚ˆ‚‰‚†‚"[‚Š‚‰‚"@‚"‚"‚'‚‰‚Ž‚‡B"

(引用符なし)

4

3 に答える 3

1

非ASCII文字/バイトに問題がある場合、それらをコンソールに印刷して、質問にコピー/貼り付けするのはかなり役に立ちません。あなたが見るものは、あなたが持っているものではないことがよくあります。組み込みrepr()関数[ ascii()Python3.x:]を使用して、データをできるだけ明確に表示する必要があります。

これを行う:

python -c "print repr(open('shiftjis.txt', 'rb').read())"

結果をコピーして貼り付け、質問を編集します。

悟りを待っている間にデータをリバースエンジニアリングする:Windowsコードページはcp1252、最も一般的なものとして、疑わしいものである必要があります。@Mark Tolonenが示したように、cp12521つのエラーで、ほぼ適合します。さらに調査すると、他のcp125xエンコーディングでは2、3、または5つのエラーが発生することがわかります。AFAIKは、cp125xエンコーディングのみがコンマ(実際にはU + 201A SINGLE LOW-9 QUOTATION MARK)のように見えるものをshift-jisリードバイトにマップします\x82cp1252違反者はであり、エラーは輸送中の損傷が原因であると結論付けます。

もう1つの可能性は、基礎となる元のエンコーディングが、日本のWindowsで使用されているshift-jisMicrosoftのスーパーセットではないことです。cp932ただし、問題のあるシーケンス'\x82@'はどちらでも有効ではありませんcp932。いずれにせよ、処理したいファイルが日本のWindowsマシンからのものである場合は、よりも使用する方がよいでしょcp932shift-jis

質問とコードから、データをUnicodeにデコードするのではなく、何をしたいのか、なぜバイト範囲でそれを実行したいのかは明らかではありません。私は使用しませんpyparsingが、あなたがそれを供給しているサブレンジが奇形である可能性が高いようです。

以下は、正規表現を使用して入力をトークン化する方法の例です。pyparsingの構文が少し異なることに注意してください(\0xffPythonの `\ xff'の代わりに)。

コード:

import re, unicodedata

input_bytes = '\x82s\x82\x88\x82\x89\x82\x93@\x82\x89\x82\x93@\x82@\x82\x93\x82\x88\x82\x89\x82\x86\x82\x94[\x82\x8a\x82\x89\x82\x93@\x82\x93\x82\x94\x82\x92\x82\x89\x82\x8e\x82\x87B'

p_ascii = r'[\x00-\x7f]'
p_hw_katakana = r'[\xa1-\xdf]' # half-width Katakana
p_jis208 = r'[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]'
p_bad = r'.' # anything else

kinds = ['jis208', 'ascii', 'hwk', 'bad']

re_matcher = re.compile("(" + ")|(".join([p_jis208, p_ascii, p_hw_katakana, p_bad]) + ")")

for mobj in re_matcher.finditer(input_bytes):
    s = mobj.group()
    us = s.decode('shift-jis', 'replace')
    print ("%-6s %-9s %-10r U+%04X %s"
        % (kinds[mobj.lastindex - 1], mobj.span(), s, ord(us), unicodedata.name(us, '<no name>'))
        )

出力:

jis208 (0, 2)    '\x82s'    U+FF34 FULLWIDTH LATIN CAPITAL LETTER T
jis208 (2, 4)    '\x82\x88' U+FF48 FULLWIDTH LATIN SMALL LETTER H
jis208 (4, 6)    '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (6, 8)    '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
ascii  (8, 9)    '@'        U+0040 COMMERCIAL AT
jis208 (9, 11)   '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (11, 13)  '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
ascii  (13, 14)  '@'        U+0040 COMMERCIAL AT
jis208 (14, 16)  '\x82@'    U+FFFD REPLACEMENT CHARACTER
jis208 (16, 18)  '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
jis208 (18, 20)  '\x82\x88' U+FF48 FULLWIDTH LATIN SMALL LETTER H
jis208 (20, 22)  '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (22, 24)  '\x82\x86' U+FF46 FULLWIDTH LATIN SMALL LETTER F
jis208 (24, 26)  '\x82\x94' U+FF54 FULLWIDTH LATIN SMALL LETTER T
ascii  (26, 27)  '['        U+005B LEFT SQUARE BRACKET
jis208 (27, 29)  '\x82\x8a' U+FF4A FULLWIDTH LATIN SMALL LETTER J
jis208 (29, 31)  '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (31, 33)  '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
ascii  (33, 34)  '@'        U+0040 COMMERCIAL AT
jis208 (34, 36)  '\x82\x93' U+FF53 FULLWIDTH LATIN SMALL LETTER S
jis208 (36, 38)  '\x82\x94' U+FF54 FULLWIDTH LATIN SMALL LETTER T
jis208 (38, 40)  '\x82\x92' U+FF52 FULLWIDTH LATIN SMALL LETTER R
jis208 (40, 42)  '\x82\x89' U+FF49 FULLWIDTH LATIN SMALL LETTER I
jis208 (42, 44)  '\x82\x8e' U+FF4E FULLWIDTH LATIN SMALL LETTER N
jis208 (44, 46)  '\x82\x87' U+FF47 FULLWIDTH LATIN SMALL LETTER G
ascii  (46, 47)  'B'        U+0042 LATIN CAPITAL LETTER B

注1:O(N ** 2)文字範囲をループして結合する必要はありません。

「jascii」が単に「FULLWIDTHLATIN(CAPITAL | SMALL)LETTER [AZ]」を意味する場合、(a)ネットが大きすぎる(b)BYTE範囲の代わりにUNICODE文字範囲を使用して簡単に行うことができます(もちろん、データ)。

于 2011-05-15T01:05:47.360 に答える
0

あなたの「テキストファイルの内容」は文字化けです(ファイルをデコードするために間違ったコーデックを使用して表示されたゴミ)。私は間違ったコーデックを推測し、テキストを再エンコードし、ShiftJISでデコードして、次のようになりました。

# coding: utf8
import codecs
s = u'‚s‚ˆ‚‰‚“@‚‰‚“@‚@‚“‚ˆ‚‰‚†‚”[‚Š‚‰‚“@‚“‚”‚’‚‰‚Ž‚‡B'
s = s.encode('cp1252').decode('shift-jis','replace')
print s

出力

This@is@�shift[jis@stringB

したがって、デフォルトの米国のWindowsコーデックは完全に正しくありません:^)

おそらく、あなたがする必要があるのは、shift_jisコーデックを使用して元のファイルを読み取ることだけです。

import codecs
f = codecs.open('shiftjis.txt','rb','shift_jis')
data = f.read()
f.close

dataデコードされた文字を含むUnicode文字列になります。

于 2011-05-14T21:07:44.683 に答える
0

私が最初に思いつくのは、ファイルをバイナリ ファイルとして開いていないということです。のようなコードを使用することをお勧めしますopen('shiftjis.txt', 'rb')。ファイルには通常の ASCII 範囲外の文字が含まれていることがわかっているため、通常は、ファイルをバイナリ ファイルとして開き、内容を Unicode にデコードすることをお勧めします。おそらく、次のようなものが機能します (「shift-jis」が正しいコーデック名であると仮定します):

text = open('shiftjis.txt', 'rb').read().decode('shift-jis')
jasciistring.parseString(text)

が(オブジェクトではなく) オブジェクトparseString()を予期している場合、最後の行を UTF-8 を使用してエンコードするように変更できます。strunicodetext

jasciistring.parseString(text.encode('utf-8'))

jasciistring私が持っている他の唯一の推奨事項は、正しい文法が含まれていることを確認することです。16 進数の範囲を使用して構築しているため、最初にバイナリとして扱いstr、次にオブジェクトにデコードする必要があると思いunicodeます。

于 2011-05-14T20:15:36.423 に答える