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

标签 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 中执行此操作,但我没有找到解决方案。我尝试过通过标记化进行替换并写入另一个文件,但没有取得太大成功。

最佳答案

首先让我们忽略我们必须保留一些关键字的事实。我们稍后会解决这个问题。

执行这种一对一映射的最简单方法是使用方法 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 字符映射到另一个字符。 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是如何保留的。

关于python - 迭代文件并替换字符串,保持字符数不变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38059397/

相关文章:

java - 确保 String 没有特定字符 (.)

regex - Notepad++ 删除两个特定字符串之间的换行符

python - 当用户使用 pip 卸载我的包时如何运行脚本?

python - 如何以恒定步长填充数组元素之间的间距,并将两个这样的数组与主要和次要优先级组合起来?

python - 在python中获取字典的一部分

ruby - 如何使用 Ruby 替换字符串中每次出现的模式?

python - 如何获取或初始化我想要的变量?

python - 尝试使用 Matplotlib 设置绘图字体时出错

ruby-on-rails - 使用 Ruby 从字符串中删除双反斜杠

python - 替换字符组合