1

改行文字がエンコードされた文字列の一部にならないように、バイナリ データをエンコード/デコードする方法を考え出そうとしています。

再帰的な問題のようですが、解決策が見つからないようです。

例: 素朴な実装:

>>> original = 'binary\ndata'

>>> encoded = original.replace('\n', '=n')
'binary=ndata'
>>> decoded = original.replace('=n', '\n')
'binary\ndata'

元の文字列に既に a がある場合はどう=nなりますか?

>>> original = 'binary\ndata=n'

>>> encoded = original.replace('\n', '=n')
'binary=ndata=n'
>>> decoded = original.replace('=n', '\n')
'binary\ndata\n'  # wrong

既存=nの をエスケープしようとしますが、エスケープされた が既にある場合はどうなり=nますか?

>>> original = '++nbinary\ndata=n'

>>> encoded = original.replace('=n', '++n').replace('\n', '=n')
'++nbinary=ndata++n'

この再帰的な問題を回避するにはどうすればよいですか?

4

7 に答える 7

1

「エスケープ」文字を含む可能性のある文字列をエンコードする方法は、エスケープ文字もエスケープすることです。Pythonでは、エスケープ文字は円記号ですが、好きなものを使用できます。あなたのコストは、改行またはエスケープが発生するたびに1文字です。

混乱を避けるために、スラッシュを使用します。

# original
>>> print "slashes / and /newline/\nhere"
slashes / and /newline/
here
# encoding
>>> print "slashes / and /newline/\nhere".replace("/", "//").replace("\n", "/n")
slashes // and //newline///nhere

すべての実際のスラッシュが2倍になるため、このエンコーディングは明確です。ただし、1回のパスでデコードする必要があるため、次の2つの連続した呼び出しを使用することはできませんreplace()

# decoding
>>> def decode(c):
    # Expand this into a real mapping if you have more substitutions
    return '\n' if c == '/n' else c[0]

>>> print "".join( decode(c) for c in re.findall(r"(/.|.)", 
                                         "slashes // and //newline///nhere"))
slashes / and /newline/
here

入力に実際のものがあることに注意してください/n(そして改行の前に別のスラッシュがあります):それはとにかくすべて正しく機能します。

于 2012-11-23T00:32:09.173 に答える
1

解決

original = 'binary\ndata \\n'
# encoded = original.encode('string_escape')                   # escape many chr
encoded = original.replace('\\', '\\\\').replace('\n', '\\n')  # escape \n and \\
decoded = encoded.decode('string_escape')

検証済み

>>> print encoded
binary\ndata \\n
>>> print decoded
binary
data \n

解決策は、Pythonでバックスラッシュでエスケープされた文字列をエスケープ解除するにはどうすればよいですか?

編集:私はあなたのアドホックな経済的エンコーディングでもそれを書きました。元の「string_escape」コーデックは、バックスラッシュ、アポストロフィ、およびchr(32)より下およびchr(126)より上のすべてをエスケープします。デコードはどちらも同じです。

于 2012-11-23T18:44:40.883 に答える
0

n 記号のアルファベット (ASCII など) を m 記号の小さいセット (改行を除く ASCII など) にエンコードする場合は、エンコードされた文字列が元の文字列よりも長くなるようにする必要があります。

これを行う典型的な方法は、1 つの文字を「エスケープ」文字として定義することです。「エスケープ」に続く文字は、エンコードされた文字を表します。この技法は、1940 年代からテレタイプライターで使用されてきました。それが、キーボードに表示される「Esc」キーの由来です。

Python (およびその他の言語) は、バックスラッシュ文字を含む文字列でこれを既に提供しています。改行は '\n' (または '\r\n') としてエンコードされます。バックスラッシュはそれ自体をエスケープするため、リテラル文字列 '\r\n' は '\\r\\n' にエンコードされます。

エスケープ文字のみを含む文字列のエンコードされた長さは、元の文字列の 2 倍になることに注意してください。それが受け入れられない場合は、より大きなアルファベットを使用するエンコーディングを使用して、エスケープ文字 (元の文字列よりも長くなる可能性があります) を回避するか、エスケープ文字を圧縮する (元の文字列よりも長くなる可能性があります) 必要があります。

于 2012-11-23T02:02:04.193 に答える
0

どうですか:

In [8]: import urllib

In [9]: original = 'binary\ndata'

In [10]: encoded = urllib.quote(original)

In [11]: encoded
Out[11]: 'binary%0Adata'

In [12]: urllib.unquote(encoded)
Out[12]: 'binary\ndata'
于 2012-11-23T21:11:54.820 に答える
0

私はバイナリデータの経験があまりないので、これは完全にオフ/非効率的/両方かもしれませんが、これで問題を回避できますか?

In [40]: original = 'binary\ndata\nmorestuff'

In [41]: nlines = [index for index, i in enumerate(original) if i == '\n']

In [42]: encoded = original.replace('\n', '')

In [43]: encoded
Out[43]: 'binarydatamorestuff'

In [44]: decoded = list(encoded)

In [45]: map(lambda x: decoded.insert(x, '\n'), nlines)
Out[45]: [None, None]

In [46]: decoded = ''.join(decoded)

In [47]: decoded
Out[47]: 'binary\ndata\nmorestuff'

繰り返しますが、はるかに優れた/より正確な方法があると確信しています-これは初心者の観点からのものです。

于 2012-11-22T23:38:56.053 に答える
0

文字列全体を体系的にエンコードすると、エスケープしてしまうのではないでしょうか? chr(ord(char) + 1) またはそのような些細なことを行うすべての文字について言いますか?

于 2012-11-22T23:34:04.543 に答える