鱼C论坛

 找回密码
 立即注册
查看: 2462|回复: 22

[已解决]re.sub()不能替换所有的非打印字符是为什么

[复制链接]
发表于 2023-7-26 10:39:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我想通过这个方法把excel表格中的非打印字符去掉,但是当我使用这个方法的时候发现他并不会把所有的非打印字符去掉,无论怎么替换,最后总是有一个askii码为28的值在。

微信图片_20230726103457.png
上面这个图片是我excel表格中的内容,后面的数字式函数code得到的前面askii的值
微信图片_20230726103543.png
这个图片是我修改后excel表格中的内容,从后面给的数字能看出来他并没有完全替换掉所有非打印字符
 def clean_data_and_save(file_path):
    try:
        # 加载现有的 Excel 文件
        workbook = load_workbook(file_path)

        # 获取工作簿中的所有工作表
        all_worksheets = workbook.worksheets

        # 正则表达式模式,用于匹配非打印字符(ASCII 控制字符)
        pattern = r'[\x00-\x1F\x7F]'

        # 遍历所有工作表
        for ws in all_worksheets:
            # 遍历当前工作表的所有单元格并清洁数据
            for row in ws.iter_rows():
                for cell in row:
                    if cell.value:
                        # 将单元格值转换为字符串
                        cleaned_value = re.sub(pattern, '*', str(cell.value))
                        cell.value = cleaned_value

        # 提取原始文件名和扩展名
        original_file_name, extension = os.path.splitext(os.path.basename(file_path))

        # 在原始文件名后添加 '_correct' 作为新的文件名
        new_file_name = original_file_name + '_correct' + extension

        # 获取文件的目录路径
        directory_path = os.path.dirname(file_path)

        # 构建新的文件路径,包含修改后的文件名
        new_file_path = os.path.join(directory_path, new_file_name)

        # 将更改后的数据保存到新的文件路径
        workbook.save(new_file_path)

        # 返回新文件的路径
        return new_file_path

    except Exception as e:
        # 处理任何异常
        print(f"错误:{e}")
        return None


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-7-26 10:39:50 | 显示全部楼层
re.sub()函数在正则表达式模式匹配时默认是区分大小写的。根据你提供的代码,我看到你使用的正则表达式模式r'[\x00-\x1F\x7F]'用于匹配非打印字符(ASCII 控制字符)。

然而,在ASCII控制字符中,值为28(即0x1C)的字符属于非打印字符,但它不在你的正则表达式模式范围内。因此,在替换过程中该字符将被保留。

要解决这个问题,你可以修改正则表达式模式,将值为 0x1C 的字符包含进去。例如,你可以将模式改为r'[\x00-\x1F\x7F\x1C]'来包含这个字符。

下面是修改后的代码示例:
import re
import openpyxl

pattern = r'[\x00-\x1F\x7F\x1C]'

# 打开 Excel 文件
workbook = openpyxl.load_workbook('path/to/your/excel/file.xlsx')

# 遍历所有工作表
for ws in workbook.worksheets:
    # 遍历当前工作表的所有单元格并清洁数据
    for row in ws.iter_rows():
        for cell in row:
            if cell.value is not None:
                # 将单元格值转换为字符串
                cleaned_value = re.sub(pattern, '*', str(cell.value))
                cell.value = cleaned_value

# 保存修改后的 Excel 文件
workbook.save('path/to/save/modified/excel/file.xlsx')

这段代码中,我添加了0x1C字符到正则表达式模式,以确保它被匹配并替换。然后,使用Openpyxl库打开Excel文件,并遍历所有工作表和单元格,将匹配到的非打印字符替换为星号*。最后,保存修改后的Excel文件。

希望这个解释能够帮助你理解为什么某些非打印字符没有被替换掉,同时提供的代码示例也能解决你的问题。如果还有其他问题,请随时提问!
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-26 10:39:53 | 显示全部楼层
在Python的正则表达式中,[\x00-\x1F\x7F]这个模式会匹配所有的ASCII控制字符,也就是ASCII值在0-31和127的字符。然而,你提到的ASCII值为28的字符并没有被替换掉。这可能是因为你的文本中的这个字符并不是一个真正的ASCII控制字符,而是一个其他字符的表示形式。

ASCII值为28的字符是文件分隔符(File Separator),在一些情况下,它可能不会被视为非打印字符。在处理这种情况时,你可以直接将这个特定的字符添加到你的正则表达式模式中,像这样:pattern = r'[\x00-\x1F\x7F|\x1C]'。

这样,你的代码就会匹配并替换所有的ASCII控制字符,以及ASCII值为28的文件分隔符。

另外,你需要注意的是,re.sub函数的第二个参数是替换字符串,如果你想要完全移除这些字符,而不是替换为'*',你应该将其设置为空字符串'',像这样:cleaned_value = re.sub(pattern, '', str(cell.value))。

希望这个答案能帮助到你。如果你还有其他问题,欢迎继续提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-26 10:46:30 | 显示全部楼层
额外加一个 .replace(chr(28), "")
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-26 10:47:10 | 显示全部楼层
isdkz 发表于 2023-7-26 10:39
在Python的正则表达式中,[\x00-\x1F\x7F]这个模式会匹配所有的ASCII控制字符,也就是ASCII值在0-31和127的 ...

我把你说的文件分隔符的已经加上了,但是我在结果中仍然可以看到这个askii28这个值,非常的奇怪
  # 正则表达式模式,用于匹配非打印字符(ASCII 控制字符)
        pattern = r'[\x00-\x1F\x7F\x1C]'

        # 遍历所有工作表
        for ws in all_worksheets:
            # 遍历当前工作表的所有单元格并清洁数据
            for row in ws.iter_rows():
                for cell in row:
                    if cell.value:
                        # 将单元格值转换为字符串
                        cleaned_value = re.sub(pattern, '', str(cell.value))
                        cell.value = cleaned_value
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-26 10:50:28 | 显示全部楼层
  # 正则表达式模式,用于匹配非打印字符(ASCII 控制字符)
        pattern = r'\s'

        # 遍历所有工作表
        for ws in all_worksheets:
            # 遍历当前工作表的所有单元格并清洁数据
            for row in ws.iter_rows():
                for cell in row:
                    if cell.value:
                        # 将单元格值转换为字符串
                        cleaned_value = re.sub(pattern, '', str(cell.value))
                        cell.value = cleaned_value
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-26 10:50:41 | 显示全部楼层
歌者文明清理员 发表于 2023-7-26 10:46
额外加一个 .replace(chr(28), "")

我不确定我这样子加对不对,但是我加上之后好像并没有什么用处
        pattern = r'[\x00-\x1F\x7F\x1C]'

        # 遍历所有工作表
        for ws in all_worksheets:
            # 遍历当前工作表的所有单元格并清洁数据
            for row in ws.iter_rows():
                for cell in row:
                    if cell.value:
                        # 将单元格值转换为字符串
                        cleaned_value = re.sub(pattern, '', str(cell.value))
                        cleaned_value=cleaned_value.replace(chr(28),'')
                        cell.value = cleaned_value
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-26 10:51:42 | 显示全部楼层
2242253525 发表于 2023-7-26 10:50
我不确定我这样子加对不对,但是我加上之后好像并没有什么用处

你确定ascii是28吗?
excel能不能传上来 wormhole.app
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-26 10:52:49 | 显示全部楼层

您这个代码我也尝试了,好像也不是很管用,非常奇怪的一个情况
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-26 10:54:52 | 显示全部楼层
这个是我的测试文件

test.rar

18.28 KB, 下载次数: 1

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-26 10:55:33 | 显示全部楼层
歌者文明清理员 发表于 2023-7-26 10:51
你确定ascii是28吗?
excel能不能传上来 wormhole.app

我传上来了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-26 10:55:45 | 显示全部楼层
Snipaste_2023-07-26_10-55-22.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-26 11:05:31 | 显示全部楼层
没有 ascii码为28的东西呀

Snipaste_2023-07-26_11-05-00.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-26 11:06:07 | 显示全部楼层

excel表格中code函数不是返回表格中第一个字符的askii码吗?我用的这个函数看的。。。。。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-26 11:07:24 | 显示全部楼层
很正常啊,70,F

Snipaste_2023-07-26_11-07-02.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-26 11:12:09 | 显示全部楼层
歌者文明清理员 发表于 2023-7-26 11:05
没有 ascii码为28的东西呀

你可以看下excel文件的第995和996行,这两行的--前面是有两个字符的,这两个字符导致我用to_excel保存我处理好的文件报错
openpyxl.utils.exceptions.IllegalCharacterError
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-26 11:15:55 | 显示全部楼层
2242253525 发表于 2023-7-26 11:12
你可以看下excel文件的第995和996行,这两行的--前面是有两个字符的,这两个字符导致我用to_excel保存我 ...

已发现,正在研究
似乎这个替换不掉
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-26 11:18:10 | 显示全部楼层
歌者文明清理员 发表于 2023-7-26 11:15
已发现,正在研究
似乎这个替换不掉

我也是看了蛮久 感觉挺怪的,或者是否有什么其他的方法让我把我处理好的dataframe变成excel也行。因为但就这个文件你用下面这个代码是没有办法保存的。
import pandas as pd
file_path = './data/input/test.xlsx'
df = pd.read_excel(file_path, header=None)
output_file_path = './data/input/1.xlsx'
df.to_excel(output_file_path, index=False)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-26 11:29:07 | 显示全部楼层
2242253525 发表于 2023-7-26 11:18
我也是看了蛮久 感觉挺怪的,或者是否有什么其他的方法让我把我处理好的dataframe变成excel也行。因为但 ...

应该是OpenPyxl过滤掉的吧,Python里没有这个空字符
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-26 11:36:19 | 显示全部楼层
歌者文明清理员 发表于 2023-7-26 11:29
应该是OpenPyxl过滤掉的吧,Python里没有这个空字符

那我应该怎么做呢?    求解决
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 0 反对 1

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-25 22:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表