迭代文件并替换字符串,保持字符数不变

时间:2016-06-27 16:59:24

标签: python replace

我正在尝试对文件进行匿名化,以便除了某些关键字之外的所有内容都被替换为乱码,但格式保持不变(包括标点符号,字符串长度和大小写)。例如:

I am testing this, check it out! This is a keyword: long
Wow, another line.

应该转到:

T ad ehistmg ptrs, erovj qo giw! Tgds ar o qpyeogf: long
Yeg, rmbjthe yadn.

我试图在python中这样做,但我没有找到解决方案的运气。我尝试通过标记化替换并写入另一个文件,但没有太大成功。

1 个答案:

答案 0 :(得分:1)

最初,我们忽略了我们必须保留一些关键字这一事实。我们稍后会解决这个问题。

执行此类1对1映射的最简单方法是使用方法str.translatestring模块还包含包含所有ASCII小写和大写字符的常量,random.shuffle可用于获取随机排列。

import string
import random

random_caps = list(string.ascii_uppercase)
random_lows = list(string.ascii_lowercase)

random.shuffle(random_caps)
random.shuffle(random_lows)

all_random_chars = ''.join(random_lows + random_caps)

translation_table = str.maketrans(string.ascii_letters, all_random_chars)

with open('the-file-i-want.txt', 'r') as f:
    contents = f.read()
    translated_contents = contents.translate(translation_table)

with open('the-file-i-want.txt', 'w') as f:
    f.write(translated_contents)

在python 2中,str.maketransstring模块中的函数,而不是str的静态方法。

translation_table是从字符到字符的映射,因此它会将每个ASCII字符映射到另一个ASCII字符。 translate方法只是将此表应用于字符串中的每个字符。

重要说明:上述方法实际上是可逆的,因为每个字母都映射到一个唯一的其他字母。这意味着通过对符号频率的简单分析,可以将其反转。

如果您想更难或不可能,可以为每一行重新创建translation_table

import string
import random

random_caps = list(string.ascii_uppercase)
random_lows = list(string.ascii_lowercase)

with open('the-file-i-want.txt', 'r') as f:
    translated_lines = []
    for line in f:
        random.shuffle(random_lows)
        random.shuffle(random_caps)
        all_random_chars = ''.join(random_lows + random_caps)

        translation_table = str.maketrans(string.ascii_letters, all_random_chars)
        translated_lines.append(line.translate(translation_table))

with open('the-file-i-want.txt', 'w') as f:
    f.writelines(translated_lines)

另请注意,您可以逐行翻译并保存文件:

with open('the-file-i-want.txt', 'r') as f, open('output.txt', 'w') as o:
    for line in f:
        random.shuffle(random_lows)
        random.shuffle(random_caps)
        all_random_chars = ''.join(random_lows + random_caps)

        translation_table = str.maketrans(string.ascii_letters, all_random_chars)
        o.write(line.translate(translation_table))

这意味着您可以使用此代码翻译大型文件,只要这些行本身并不长。

以上代码弄乱所有字符,而不考虑此类关键字。

处理要求的最简单方法是简单地检查每一行是否出现一个关键字并在那里“重新插入”:

import re
import string
import random

random_caps = list(string.ascii_uppercase)
random_lows = list(string.ascii_lowercase)

keywords = ['long']   # add all the possible keywords in this list

keyword_regex = re.compile('|'.join(re.escape(word) for word in keywords))


with open('the-file-i-want.txt', 'r') as f, open('output.txt', 'w') as o:
    for line in f:
        random.shuffle(random_lows)
        random.shuffle(random_caps)
        all_random_chars = ''.join(random_lows + random_caps)

        translation_table = str.maketrans(string.ascii_letters, all_random_chars)
        matches = keyword_regex.finditer(line)
        translated_line = list(line.translate(translation_table))

        for match in matches:
            translated_line[match.start():match.end()] = match.group()

        o.write(''.join(translated_line))

示例用法(使用主流关键字的版本):

$ echo 'I am testing this, check it out! This is a keyword: long
Wow, another line.' > the-file-i-want.txt
$ python3 trans.py 
$ cat output.txt 
M vy hoahitc hfia, ufoum ih pzh! Hfia ia v modjpel: long
Ltj, fstkwzb hdsz.

请注意long如何保留。