当前位置: 首页 > article >正文

python制作自己的一款Markdowm格式消除工具

01 引言 

在日常使用 Markdown 编写文档时,我们有时会需要将 Markdown 格式的文本转换为纯文本,去除其中的各种标记符号,如标题符号、列表符号、代码块标记等。手动去除这些标记不仅效率低下,还容易出错。本文将介绍如何使用 Python 和 PyQt5 库来创建一个简单易用的 Markdown 格式消除工具,并且支持实时预览和文件保存功能。 

02 环境准备 

在开始之前,我们需要安装一些必要的库。主要用到的是 PyQt5 用于创建图形用户界面(GUI),以及 Python 内置的 re 库用于正则表达式匹配,用于去除 Markdown 格式。可以使用以下命令来安装 PyQt5:

pip install PyQt5

03 实现思路

我们的 Markdown 格式消除工具主要包含以下几个部分:

  1. 图形用户界面(GUI):使用 PyQt5 创建一个窗口,包含输入框、输出框和一些操作按钮,如导入文本、清除格式、复制文本、保存文本等。
  2. Markdown 格式处理:使用正则表达式匹配 Markdown 标记符号,并将其替换为空字符串,从而实现格式消除。
  3. 实时预览:当用户在输入框中输入或修改 Markdown 文本时,实时更新输出框中的纯文本内容。
  4. 文件操作:支持直接拖入或导入 Markdown 文件和保存处理后的纯文本文件。

04 完整代码

import sys
import re
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QTextEdit, QPushButton, QLabel, QFileDialog, QHBoxLayout
)
from PyQt5.QtGui import QFont, QClipboard
from PyQt5.QtCore import Qt, pyqtSlotclass MarkdownRemoverApp(QWidget):def __init__(self):super().__init__()self.dark_theme = False  # 初始为亮色主题self.setAcceptDrops(True)  # 启用拖放功能self.init_ui()def init_ui(self):"""初始化界面"""# 设置窗口标题和大小self.setWindowTitle("Markdown 格式清除工具")self.setGeometry(100, 100, 800, 800)# 设置全局字体font = QFont("Arial", 12)self.setFont(font)# 整体水平布局main_h_layout = QHBoxLayout()# 左侧文本编辑区域垂直布局left_v_layout = QVBoxLayout()# 原始 Markdown 文本部分self.left_label = QLabel("原始 Markdown 文本")self.left_label.setStyleSheet("font-size: 14px; font-weight: bold;")self.left_text_edit = QTextEdit()self.left_text_edit.setStyleSheet("background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px;")left_v_layout.addWidget(self.left_label)left_v_layout.addWidget(self.left_text_edit)# 清除 Markdown 后的文本部分self.right_label = QLabel("清除 Markdown 后的文本")self.right_label.setStyleSheet("font-size: 14px; font-weight: bold;")self.right_text_edit = QTextEdit()self.right_text_edit.setStyleSheet("background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px;")left_v_layout.addWidget(self.right_label)left_v_layout.addWidget(self.right_text_edit)# 右侧按钮垂直布局right_v_layout = QVBoxLayout()# 导入文本按钮self.import_button = QPushButton("导入文本")self.import_button.setStyleSheet("""QPushButton {background-color: #4CAF50;color: white;font-family: Arial;font-size: 14px;font-weight: bold;padding: 12px 20px;border-radius: 8px;border: none;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);}QPushButton:hover {background-color: #66BB6A;box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);}QPushButton:pressed {background-color: #388E3C;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);transform: translateY(2px);}""")self.import_button.setCursor(Qt.PointingHandCursor)self.import_button.clicked.connect(self.import_text)# 一键复制按钮self.copy_button = QPushButton("一键复制")self.copy_button.setStyleSheet("""QPushButton {background-color: #FF9800;color: white;font-family: Arial;font-size: 14px;font-weight: bold;padding: 12px 20px;border-radius: 8px;border: none;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);}QPushButton:hover {background-color: #FFB74D;box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);}QPushButton:pressed {background-color: #F57C00;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);transform: translateY(2px);}""")self.copy_button.setCursor(Qt.PointingHandCursor)self.copy_button.clicked.connect(self.copy_text)# 一键清除按钮self.clear_all_button = QPushButton("一键清除")self.clear_all_button.setStyleSheet("""QPushButton {background-color: #F44336;color: white;font-family: Arial;font-size: 14px;font-weight: bold;padding: 12px 20px;border-radius: 8px;border: none;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);}QPushButton:hover {background-color: #EF5350;box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);}QPushButton:pressed {background-color: #D32F2F;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);transform: translateY(2px);}""")self.clear_all_button.setCursor(Qt.PointingHandCursor)self.clear_all_button.clicked.connect(self.clear_all_text)# 主题切换按钮self.theme_button = QPushButton("切换主题")self.theme_button.setStyleSheet("""QPushButton {background-color: #607D8B;color: white;font-family: Arial;font-size: 14px;font-weight: bold;padding: 12px 20px;border-radius: 8px;border: none;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);}QPushButton:hover {background-color: #78909C;box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);}QPushButton:pressed {background-color: #546E7A;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);transform: translateY(2px);}""")self.theme_button.setCursor(Qt.PointingHandCursor)self.theme_button.clicked.connect(self.toggle_theme)# 保存处理后文本按钮self.save_button = QPushButton("保存处理后的文本")self.save_button.setStyleSheet("""QPushButton {background-color: #9E9E9E;color: white;font-family: Arial;font-size: 14px;font-weight: bold;padding: 12px 20px;border-radius: 8px;border: none;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);}QPushButton:hover {background-color: #BDBDBD;box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);}QPushButton:pressed {background-color: #757575;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);transform: translateY(2px);}""")self.save_button.setCursor(Qt.PointingHandCursor)self.save_button.clicked.connect(self.save_text)# 将按钮添加到右侧按钮布局right_v_layout.addWidget(self.import_button)right_v_layout.addWidget(self.copy_button)right_v_layout.addWidget(self.clear_all_button)right_v_layout.addWidget(self.theme_button)right_v_layout.addWidget(self.save_button)# 将左侧文本编辑区域布局和右侧按钮布局添加到整体水平布局main_h_layout.addLayout(left_v_layout)main_h_layout.addLayout(right_v_layout)# 设置主布局self.setLayout(main_h_layout)# 连接文本改变信号实现实时预览self.left_text_edit.textChanged.connect(self.update_preview)@pyqtSlot()def update_preview(self):"""实时更新清除 Markdown 格式后的文本预览"""markdown_text = self.left_text_edit.toPlainText()cleaned_text = self._remove_markdown(markdown_text)self.right_text_edit.setPlainText(cleaned_text)def import_text(self):"""导入文本文件"""# 打开文件选择对话框file_path, _ = QFileDialog.getOpenFileName(self, "选择文本文件", "", "文本文件 (*.txt);;所有文件 (*)")if file_path:# 读取文件内容try:with open(file_path, "r", encoding="utf-8") as file:content = file.read()# 将内容加载到左侧文本框self.left_text_edit.setPlainText(content)except Exception as e:print(f"读取文件出错: {e}")def copy_text(self):"""将清除 Markdown 格式后的文本复制到剪贴板"""clipboard = QApplication.clipboard()cleaned_text = self.right_text_edit.toPlainText()clipboard.setText(cleaned_text)def clear_all_text(self):"""一键清除左右文本框的内容"""self.left_text_edit.clear()self.right_text_edit.clear()def _remove_markdown(self, text):"""移除 Markdown 格式并返回纯文本"""# 转换转义字符text = re.sub(r'\\([\\`*{}[\]()\#+\-.!_>~|])', r'\1', text)# 删除代码块(多行)text = re.sub(r'```[\s\S]*?```', '', text)# 删除行内代码text = re.sub(r'`([^`]+)`', r'\1', text)# 处理图片和链接text = re.sub(r'!\[(.*?)\]\([^)]*\)', r'\1', text)  # 图片text = re.sub(r'\[(.*?)\]\([^)]*\)', r'\1', text)  # 链接# 处理粗体/斜体text = re.sub(r'\*\*(\*?[\s\S]+?)\*\*', r'\1', text)  # **bold**text = re.sub(r'__([\s\S]+?)__', r'\1', text)  # __underline__text = re.sub(r'\*([\s\S]+?)\*', r'\1', text)  # *italic*text = re.sub(r'_([\s\S]+?)_', r'\1', text)  # _italic_# 清除标题符号text = re.sub(r'^#+\s*', '', text, flags=re.MULTILINE)# 清除列表符号(支持多级列表)text = re.sub(r'^([\s]*[-*+]|\d+\.)\s+', '', text, flags=re.MULTILINE)# 清除引用块符号text = re.sub(r'^>\s*', '', text, flags=re.MULTILINE)# 清除分隔线text = re.sub(r'^[-*_]{3,}\s*$', '', text, flags=re.MULTILINE)# 合并多余空行并去除首尾空白text = re.sub(r'\n{3,}', '\n\n', text)return text.strip()def toggle_theme(self):if self.dark_theme:# 切换到亮色主题self.setStyleSheet("")self.left_text_edit.setStyleSheet("background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px;")self.right_text_edit.setStyleSheet("background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px;")self.left_label.setStyleSheet("font-size: 14px; font-weight: bold;")self.right_label.setStyleSheet("font-size: 14px; font-weight: bold;")self.dark_theme = Falseelse:# 切换到暗色主题self.setStyleSheet("background-color: #212121; color: white;")self.left_text_edit.setStyleSheet("background-color: #424242; border: 1px solid #616161; padding: 10px; color: white;")self.right_text_edit.setStyleSheet("background-color: #424242; border: 1px solid #616161; padding: 10px; color: white;")self.left_label.setStyleSheet("font-size: 14px; font-weight: bold; color: white;")self.right_label.setStyleSheet("font-size: 14px; font-weight: bold; color: white;")self.dark_theme = Truedef save_text(self):"""保存处理后的文本到指定文件"""file_path, _ = QFileDialog.getSaveFileName(self, "保存文件", "", "文本文件 (*.txt)")if file_path:try:text = self.right_text_edit.toPlainText()with open(file_path, 'w', encoding='utf-8') as file:file.write(text)except Exception as e:print(f"保存文件出错: {e}")def dragEnterEvent(self, event):"""处理拖入事件,检查是否是文件"""if event.mimeData().hasUrls():for url in event.mimeData().urls():if url.toLocalFile().endswith(('.txt', '.md')):event.acceptProposedAction()returnevent.ignore()def dropEvent(self, event):"""处理放下事件,读取文件内容并加载到左侧文本框"""for url in event.mimeData().urls():file_path = url.toLocalFile()if file_path.endswith(('.txt', '.md')):try:with open(file_path, 'r', encoding='utf-8') as file:content = file.read()self.left_text_edit.setPlainText(content)except Exception as e:print(f"读取文件出错: {e}")# 主程序入口
if __name__ == "__main__":app = QApplication(sys.argv)window = MarkdownRemoverApp()window.show()sys.exit(app.exec_())

05 运行结果 

相关文章:

python制作自己的一款Markdowm格式消除工具

01 引言 在日常使用 Markdown 编写文档时,我们有时会需要将 Markdown 格式的文本转换为纯文本,去除其中的各种标记符号,如标题符号、列表符号、代码块标记等。手动去除这些标记不仅效率低下,还容易出错。本文将介绍如何使用 Pyt…...

【C#零基础从入门到精通】(三)——C#变量和数据类型详解

【C#零基础从入门到精通】(三)——C#变量和数据类型详解 数据类型 在 C# 中,数据类型是对数据进行分类的方式,它定义了变量可以存储的数据的种类、范围以及可以对这些数据执行的操作。C# 的数据类型主要分为值类型、引用类型和指针类型(指针类型通常在不安全代码中使用),…...

如何从头训练大语言模型: A simple technical report

今天来快速捋一下路线,写个简短的technical report,更多是原理介绍性的。按我个人理解,从最简单的部分开始,逐步过渡到最繁复的环节: 模型架构-> Pretrain -> Post-Train -> Infra -> 数据侧。再掺杂一些杂项&#xf…...

gitlab无法登录问题

在我第一次安装gitlab的时候发现登录页面是 正常的页面应该是 这种情况的主要原因是不是第一次登录,所以我们要找到原先的密码 解决方式: [rootgitlab ~]# vim /etc/gitlab/initial_root_password# WARNING: This value is valid only in the followin…...

食品饮料生产瓶颈?富唯智能协作机器人来 “破壁”

在食品和饮料行业的发展进程中,诸多生产瓶颈如重复性劳动负担、复杂环境作业难题、季节性产能波动等,长期制约着企业的高效运营与进一步发展。如今,富唯智能协作机器人的出现,为这些难题提供了完美的解决方案,正逐步改…...

Python 实现 macOS 系统代理的设置

设置 SOCKS 代理 在 macOS 系统中,可以通过 networksetup 工具来设置 SOCKS 代理。以下是 Python 实现的方法: 使用 networksetup 设置 SOCKS 代理 import subprocessdef set_socks_proxy(server, port):"""设置 macOS 系统的 SOCKS 代理…...

深度学习之神经网络框架搭建及模型优化

神经网络框架搭建及模型优化 目录 神经网络框架搭建及模型优化1 数据及配置1.1 配置1.2 数据1.3 函数导入1.4 数据函数1.5 数据打包 2 神经网络框架搭建2.1 框架确认2.2 函数搭建2.3 框架上传 3 模型优化3.1 函数理解3.2 训练模型和测试模型代码 4 最终代码测试4.1 SGD优化算法…...

excel 日期转换

需求如下: 在excel 里面输入一个4515,4表示年份,2024年,51表示该年的51周,5表示日,周日用1表示,周一用2表示,以此类推,需要转换为年份/月份/日期 若想用公式来实现这一转换&#x…...

Awtk 如何添加开机画面

场景 我们知道在工程中,Ui是一个线程,并且需要一直存在,当我们使用的开机画面在这个线程开启就直接展示的时候,因为awtk的界面是window_open入栈的,即首次打开的窗口会记录在top,往后的窗口会依次往后存放&…...

【设计模式】【行为型模式】命令模式(Command)

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD 🔥 2025本人正在沉淀中… 博客更新速度 📫 欢迎V: flzjcsg2,我们共同讨论Java深渊的奥秘 &#x1f…...

C++模拟实现AVL树

目录 1.文章概括 2.AVL树概念 3.AVL树的性质 4.AVL树的插入 5.旋转控制 1.左单旋 2. 右单旋 3.左右双旋 4.右左双旋 6.全部代码 1.文章概括 本文适合理解平衡二叉树的读者阅读,因为AVL树是平衡二叉树的一种优化,其大部分实现逻辑与平衡二叉树是…...

推荐算法实践:movielens数据集

MovieLens 数据集介绍 MovieLens 数据集是由明尼苏达大学的GroupLens研究小组维护的一个广泛使用的电影评分数据集,主要用于推荐系统的研究。该数据集包含用户对电影的评分、标签以及其他相关信息,是电影推荐系统开发与研究的常用数据源。 数据集版本 …...

dynamic_cast和static_cast和const_cast

dynamic_cast 在 C 中的作用 dynamic_cast 是 C 运行时类型转换(RTTI, Run-Time Type Identification)的一部分,主要用于: 安全的多态类型转换检查类型的有效性向下转换(Downcasting)跨类层次的指针或引用…...

React进行路由跳转的方法汇总

在 React 中进行路由跳转有多种方法,具体取决于你使用的路由库和版本。以下是常见的路由跳转方法汇总,主要基于 react-router-dom 库。 1. 使用 useNavigate 钩子(适用于 react-router-dom v6) useNavigate 是 react-router-dom…...

python卷积神经网络人脸识别示例实现详解

目录 一、准备 1)使用pytorch 2)安装pytorch 3)准备训练和测试资源 二、卷积神经网络的基本结构 三、代码实现 1)导入库 2)数据预处理 3)加载数据 4)构建一个卷积神经网络 5&#xff0…...

以Unity6.0为例,如何在Unity中开启DLSS功能

DLSS DLSS(NVIDIA 深度学习超级采样):NVIDIA DLSS 是一套由 GeForce RTX™ Tensor Core 提供支持的神经渲染技术,可提高帧率,同时提供可与原生分辨率相媲美的清晰、高质量图像。目前最新突破DLSS 4 带来了新的多帧…...

CSDN 大模型 笔记

AI 3大范式:计算 发发 交互 L1 生成代码 复制到IDEA (22年12-23年6,7月份) L2 部分自动编程 定义class 设计interface 让其填充实现 (23年7,8月份) L3 通用任务 CRUD (24年) L4 高度自动编程 通用领域专有任务&#xf…...

Flink怎么保证Exactly - Once 语义

Exactly - Once 语义是消息处理领域中的一种严格数据处理语义,指每条数据都只会被精确消费和处理一次,既不会丢失,也不会重复。 以下从消息传递语义对比、实现方式、应用场景等方面详细介绍: 与其他消息传递语义对比 在消息传递…...

AOS安装及操作演示

文章目录 一、安装node1.1 在 macOS 上管理 Node版本1.1.1 安装 nvm1.1.2 验证 nvm 是否安装成功1.1.3 使用 nvm 安装/切换 Node.js 版本1.1.4 卸载 Node.js 版本 1.2 在 windows 上管理 Node版本1.2.1 安装 nvm-windows1.2.2 安装 Node.js 版本1.2.3 切换 Node.js 版本1.2.4 卸…...

Python 操作 MongoDB 教程

一、引言 在当今数字化时代,数据的存储和管理至关重要。传统的关系型数据库在处理一些复杂场景时可能会显得力不从心,而 NoSQL 数据库应运而生。MongoDB 作为一款开源的、面向文档的 NoSQL 数据库,凭借其高性能、高可扩展性和灵活的数据模型…...

Stability AI 联合 UIUC 提出单视图 3D 重建方法SPAR3D,可0.7秒完成重建并支持交互式用户编辑。

Stability AI 联合 UIUC 提出一种简单而有效的单视图 3D 重建方法 SPAR3D,这是一款最先进的 3D 重建器,可以从单视图图像重建高质量的 3D 网格。SPAR3D 的重建速度很快,只需 0.7 秒,并支持交互式用户编辑。 相关链接 论文&#xf…...

网易易盾接入DeepSeek,数字内容安全“智”理能力全面升级

今年农历新年期间,全球AI领域再度掀起了一波革命性浪潮,国产通用大模型DeepSeek凭借其强大的多场景理解与内容生成能力迅速“出圈”,彻底改写全球人工智能产业的格局。 作为国内领先的数字内容风控服务商,网易易盾一直致力于探索…...

自动驾驶---如何打造一款属于自己的自动驾驶系统

在笔者的专栏《自动驾驶Planning决策规划》中,主要讲解了行车的相关知识,从Routing,到Behavior Planning,再到Motion Planning,以及最后的Control,笔者都做了相关介绍,其中主要包括算法在量产上…...

局域网使用Ollama(Linux)

解决局域网无法连接Ollama服务的问题 在搭建和使用Ollama服务的过程中,可能会遇到局域网内无法连接的情况。经过排查发现,若开启了代理软件,尤其是Hiddify,会导致此问题。这一发现耗费了我数小时的排查时间,希望能给大…...

聚焦 AUTO TECH China 2025,共探汽车内外饰新未来Automotive Interiors

全球汽车产业蓬勃发展的大背景下,汽车内外饰作为汽车重要组成部分,其市场需求与技术创新不断推动着行业变革。2025年11月20日至22日,一场备受瞩目的行业盛会 ——AUTO TECH China 2025 广州国际汽车内外饰技术展览会将在广州保利世贸博览馆盛…...

Moretl 增量文件采集工具

永久免费: <下载> <使用说明> 用途 定时全量或增量采集工控机,电脑文件或日志. 优势 开箱即用: 解压直接运行.不需额外下载.管理设备: 后台统一管理客户端.无人值守: 客户端自启动,自更新.稳定安全: 架构简单,兼容性好,通过授权控制访问. 架构 技术架构: Asp…...

支持多种网络数据库格式的自动化转换工具——VisualXML

一、VisualXML软件介绍 对于DBC、ARXML……文件的编辑、修改等繁琐操作&#xff0c;WINDHILL风丘科技开发的总线设计工具——VisualXML&#xff0c;可轻松解决这一问题&#xff0c;提升工作效率。 VisualXML是一个强大且基于Excel表格生成多种网络数据库文件的转换工具&#…...

mysql8 用C++源码角度看客户端发起sql网络请求,并处理sql命令

MySQL 8 的 C 源码中&#xff0c;处理网络请求和 SQL 命令的流程涉及多个函数和类。以下是关键的函数和类&#xff0c;以及它们的作用&#xff1a; 1. do_command 函数 do_command 函数是 MySQL 服务器中处理客户端命令的核心函数。它从客户端读取一个命令并执行。这个函数在…...

四、OSG学习笔记-基础图元

前一章节&#xff1a; 三、OSG学习笔记-应用基础-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145514021 代码&#xff1a;CuiQingCheng/OsgStudy - Gitee.com 一、绘制盒子模型 下面一个简单的 demo #include<windows.h> #include<osg/Node&…...

使用vllm docker容器部署大语言模型

说明 最近deepseek比较火&#xff0c;我在一台4卡4090的服务器上尝试部署了一下&#xff0c;记录下部署步骤。 安装过程 安卓docker和nvidia-container-toolkit 安装19.03版本以上的docker-ce即可。安装步骤参考清华docker源上的安装步骤&#xff1a;Docker CE 软件仓库 为…...