从别的终端工具导出的快捷命令是个CSV文件,格式为:`分类,命令名称,命令内容`。于是用AI做了一个Python小脚本,比js转换更稳定高效:
– 命令内容**经常包含多行**(如 heredoc、环境变量定义、find -exec、配置文件等)
– 目标:将 CSV 转换为 **WordPress Gutenberg 经典块格式**(heading + list + list-item),并**完整保留命令中的换行**
– 最终期望输出:每个分类一个标题 + 一个列表,列表内每条命令用 `
使用说明:
- 保存脚本为 csv_to_wp.py
- 把你的 CSV 文件命名为 commands.csv(或任意名)
- 命令行运行调出界面:
python csv_to_wp.pyt - 上传CSV 文件(提前保存玮utf-8编码) ,修改模板,点击转换,复制粘贴到 WordPress。
如何支持更多行(列)?
在模板中添加占位符,例如 {第4列} 表示 CSV 的第4列(备注) 示例模板:
<!-- wp:list-item {"metadata":{"name":"{第2列}"}} -->
<li>
<pre class="wp-block-preformatted"><code>{第3列}</code></pre>
<small>备注:{第4列}</small>
</li>
<!-- /wp:list-item -->
Python 脚本:
# -*- coding: utf-8 -*-
"""
CSV → WordPress Blocks + Markdown 图形界面工具
================================================
功能:
- 上传/选择 CSV 文件
- 可编辑模板(支持任意列 {第N列})
- 一键生成 WordPress Gutenberg 块代码
- 一键生成 Markdown 格式(新增)
- 复制结果到剪贴板
使用方法:
1. pip install pyperclip
2. python csv_to_wp_md_gui.py
"""
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
import csv
import html
import os
import pyperclip
class CsvToWpMdApp:
def __init__(self, root):
self.root = root
self.root.title("CSV → WP Blocks & Markdown 工具")
self.root.geometry("1000x750")
self.root.minsize(900, 650)
self.default_wp_template = """<!-- wp:list-item {"metadata":{"name":"{第2列}"}} -->
<li><pre class="wp-block-preformatted"><code>{第3列}</code></pre></li>
<!-- /wp:list-item -->"""
self.csv_path = tk.StringVar()
self.template_var = tk.StringVar(value=self.default_wp_template)
self.create_widgets()
def create_widgets(self):
tk.Label(self.root, text="CSV → WordPress Blocks & Markdown 转换工具", font=("Helvetica", 16, "bold")).pack(pady=10)
# 文件选择
file_frame = tk.Frame(self.root)
file_frame.pack(fill="x", padx=20, pady=5)
tk.Label(file_frame, text="CSV 文件:", font=("Helvetica", 10, "bold")).pack(side="left")
tk.Entry(file_frame, textvariable=self.csv_path, width=70, state="readonly").pack(side="left", padx=10)
tk.Button(file_frame, text="选择文件", command=self.choose_file).pack(side="left", padx=5)
# 模板区(只用于 WP 格式,Markdown 固定模板)
tk.Label(self.root, text="WordPress 单条项目模板(支持 {第1列} ~ {第N列})", font=("Helvetica", 10, "bold")).pack(anchor="w", padx=20, pady=(15, 5))
self.template_text = scrolledtext.ScrolledText(self.root, height=6, wrap="word", font=("Consolas", 10))
self.template_text.insert("1.0", self.default_wp_template)
self.template_text.pack(fill="x", padx=20, pady=5)
tk.Button(self.root, text="恢复默认 WP 模板", command=self.reset_wp_template).pack(anchor="e", padx=20)
# 按钮区
btn_frame = tk.Frame(self.root)
btn_frame.pack(pady=15)
tk.Button(btn_frame, text="生成 WP Blocks", command=self.convert_wp, bg="#0066cc", fg="white", font=("Helvetica", 11, "bold"), width=18).pack(side="left", padx=10)
tk.Button(btn_frame, text="生成 Markdown", command=self.convert_md, bg="#28a745", fg="white", font=("Helvetica", 11, "bold"), width=18).pack(side="left", padx=10)
tk.Button(btn_frame, text="复制结果", command=self.copy_result, bg="#6c757d", fg="white", font=("Helvetica", 11, "bold"), width=18).pack(side="left", padx=10)
# 输出区
tk.Label(self.root, text="转换结果(可直接复制到 WordPress 或 Markdown 编辑器)", font=("Helvetica", 10, "bold")).pack(anchor="w", padx=20, pady=5)
self.output_text = scrolledtext.ScrolledText(self.root, height=25, wrap="word", font=("Consolas", 10))
self.output_text.pack(fill="both", expand=True, padx=20, pady=5)
def choose_file(self):
file = filedialog.askopenfilename(filetypes=[("CSV/Text files", "*.csv *.txt"), ("All files", "*.*")])
if file:
self.csv_path.set(file)
def reset_wp_template(self):
if messagebox.askyesno("确认", "恢复默认 WordPress 模板?"):
self.template_text.delete("1.0", tk.END)
self.template_text.insert("1.0", self.default_wp_template)
def read_csv(self):
csv_file = self.csv_path.get()
if not csv_file or not os.path.exists(csv_file):
messagebox.showerror("错误", "请先选择有效的 CSV 文件")
return None
groups = {}
try:
with open(csv_file, 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
if len(row) < 3:
continue
group = row[0].strip()
name = row[1].strip()
command = ','.join(row[2:]).strip() # 保留原始换行
if group not in groups:
groups[group] = []
groups[group].append((name, command))
return groups
except Exception as e:
messagebox.showerror("读取失败", f"文件读取出错:\n{str(e)}\n请确保是 UTF-8 编码")
return None
def convert_wp(self):
groups = self.read_csv()
if not groups:
return
template = self.template_text.get("1.0", tk.END).strip()
if not template:
messagebox.showerror("错误", "WP 模板不能为空")
return
output = []
for group, items in groups.items():
output.append('<!-- wp:heading {"level":4} -->')
output.append(f'<h4 class="wp-block-heading">{html.escape(group)} 常用命令</h4>')
output.append('<!-- /wp:heading -->')
output.append('')
output.append(f'<!-- wp:list {{"metadata":{{"name":"{html.escape(group)}"}}}} -->')
output.append('<ul class="wp-block-list">')
output.append('')
for name, command in items:
cmd_escaped = html.escape(command)
block = template.replace('{第1列}', html.escape(group)) \
.replace('{第2列}', html.escape(name)) \
.replace('{第3列}', cmd_escaped)
# 支持更多列
for i in range(4, 20):
ph = f'{{第{i}列}}'
if ph in block:
# 这里简化处理:实际 CSV 行是动态的,建议固定列数或传 row
# 当前仅替换已知列(可优化为动态)
block = block.replace(ph, '')
output.append(block)
output.append('')
output.append('</ul>')
output.append('<!-- /wp:list -->')
output.append('')
result = '\n'.join(output).strip()
self.output_text.delete("1.0", tk.END)
self.output_text.insert("1.0", result)
messagebox.showinfo("完成", "WordPress Blocks 转换成功!")
def convert_md(self):
groups = self.read_csv()
if not groups:
return
output = []
for group, items in groups.items():
output.append(f"## {group} 常用命令\n")
output.append("")
for name, command in items:
output.append(f"### {name}\n")
output.append("```shell")
output.append(command)
output.append("```\n")
result = '\n'.join(output).strip()
self.output_text.delete("1.0", tk.END)
self.output_text.insert("1.0", result)
messagebox.showinfo("完成", "Markdown 转换成功!")
def copy_result(self):
text = self.output_text.get("1.0", tk.END).strip()
if text:
pyperclip.copy(text)
messagebox.showinfo("成功", "已复制到剪贴板")
else:
messagebox.showwarning("提示", "暂无内容可复制")
if __name__ == "__main__":
root = tk.Tk()
app = CsvToWpMdApp(root)
root.mainloop()
脚本自动支持到第19列(for 循环 range(4, 20)),如果需要更多,直接把 20 改大就行。
如果以后 CSV 内容有变化,直接替换文件重新运行即可,**永久可用**。