如何在gnuplot中处理CSV文件与多行标签?
处理gnuplot中CSV多行标签的问题
问题场景
我有一份从LibreOffice导出的标准CSV文件MultilineLabels.csv,重新导入LibreOffice时能正常显示单元格内的多行文本。文件内容如下:
1,Simple,1.3 2,Single line,2.3 3,"Multiline label",3.3 4,Simple again,4.3 5,Multiline\nlabel,5.3 6,Simple again,6.3
使用以下gnuplot脚本绘图时:
### How to handle CSV and multi-line labels in gnuplot? reset session FILE = "MultilineLabels.csv" set datafile separator comma set format x "\n" plot FILE u 1:3:xtic(2) w lp pt 7 lc "red" ### end of script
发现x=3对应的点和标签未被绘制——原因是gnuplot没有专门的CSV输入过滤器,会把双引号内的实际换行识别为新的数据行,导致该行数据被拆分,无法正确解析。
解决方案:不止替换换行这一种方式
方案1:用外部工具预处理文件(高效简洁)
借助sed这类文本处理工具,提前将双引号内的实际换行替换为\n,生成处理后的临时文件供gnuplot使用。示例脚本:
reset session FILE = "MultilineLabels.csv" TMP_FILE = "tmp_processed.csv" # 用sed合并双引号内的多行,将换行替换为\n system(sprintf('sed -e ''/^[^"]*"[^"]*$/ { :a; N; /"[^"]*$/ !ba; s/\n/\\n/g; }'' %s > %s', FILE, TMP_FILE)) set datafile separator comma plot TMP_FILE u 1:3:xtic(2) w lp pt 7 lc "red"
方案2:纯gnuplot脚本处理(无外部依赖)
如果不想依赖外部工具,可以用gnuplot的内置逻辑逐行读取文件,手动处理双引号包裹的多行内容:
reset session FILE = "MultilineLabels.csv" TMP_FILE = "tmp_processed.csv" # 创建临时文件并写入处理后的数据 set print TMP_FILE in_quotes = 0 line_buffer = "" # 逐行读取原文件 do for [line in system(sprintf('cat %s', FILE))] { if (!in_quotes) { # 统计当前行的双引号数量,判断是否开启引号包裹 quote_count = sum [i=1:strlen(line)] (substr(line,i,1) eq '"' ? 1 : 0) if (quote_count % 2 == 1) { in_quotes = 1 line_buffer = line } else { print line } } else { # 处于引号包裹状态,合并行并替换实际换行为\n line_buffer = line_buffer . "\n" . line quote_count = sum [i=1:strlen(line)] (substr(line,i,1) eq '"' ? 1 : 0) if (quote_count % 2 == 1) { in_quotes = 0 print line_buffer line_buffer = "" } } } set print set datafile separator comma plot TMP_FILE u 1:3:xtic(2) w lp pt 7 lc "red"
总结
替换双引号内的换行是解决这类问题的常用思路,但并非唯一方案:
- 用外部工具预处理适合处理大文件,执行效率更高;
- 纯gnuplot脚本的方式无需额外依赖,兼容性更好,适合跨环境使用。
内容的提问来源于stack exchange,提问作者theozh
相关产品推荐
相关产品推荐

