我有一个后续问题https://tex.stackexchange.com/a/598981/46023
MWE 中的一切都正常,但是在我的原始示例中使用时它不再起作用(注意:originaltable.csv 是原始版本的大大缩短版本,其中包含比较、计算等)。
originaltable.csv 中所写的“Molybdän”一词中的变音符号“ä”是有问题的。
\begin{filecontents}[overwrite]{originaltable.csv}
Z; Symbol; Name
2; He; Helium
41; Mo; Molybdän
\end{filecontents}
\documentclass{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\pgfplotstableread[col sep=semicolon, header=true]{originaltable.csv} {\psetable}
% Methode % https://tex.stackexchange.com/a/598981/46023
\makeatletter
\long\def\protected@iwrite#1#2#3{\begingroup%
#2%
\let\protect\@unexpandable@protect%
\edef\reserved@a{\immediate\write#1{#3}}%
\reserved@a%
\endgroup%
\if@nobreak\ifvmode\nobreak\fi\fi}
\newcommand{\mywrite}[2]{\protected@iwrite#1{}{#2}}%
\makeatother
\begin{document}
\newwrite\out
\immediate\openout\out=out.csv
\foreach[count=\n from 0] \row in {0,1}{%%
% In:
\pgfplotstablegetelem{\row}{Z}\of{\psetable}
\xdef\Z{\pgfplotsretval}%
\pgfplotstablegetelem{\row}{Symbol}\of{\psetable}%
\xdef\Symbol{\pgfplotsretval}%
\pgfplotstablegetelem{\row}{Name}\of{\psetable}%
\xdef\Name{\pgfplotsretval}%
% Out:
\mywrite\out{\Z; \Symbol; \Name}% does not work :(
}%%
\immediate\closeout\out
%\input{out.csv}
% Target in:
\pgfplotstableread[col sep=semicolon, header=false]{out.csv}{\mytable}
\pgfplotstabletypeset[string type]{\mytable}
\end{document}
答案1
问题在于 pdfLaTeX 如何处理 ä(和其他重音字符)。快速简单的解决方案:使用 XeLaTeX 或 LuaLaTeX。
你遇到麻烦的地方是当\xdef
你\pgfplotsretval
您会绕过任何可能存在的扩展保护。最简单的解决方法是不是使用\xdef
,而是使用\let
。我在这个答案中谈到了\let
与定义宏https://tex.stackexchange.com/a/598902/202780昨天。这是一个\let
完全适合这项工作的工具的案例。
如果您想这样做\edef
,LaTeX 提供的选项要求超出用户级命令的范围,使用私有命令\protected@edef
或 expl3 等效命令,这是我目前无法找到的,我在粗略浏览 interface3.pdf 时找不到,但我相信大卫卡莱尔会跳出来提供它,即使在这种情况下\let
是最好的解决方案。
答案2
没有理由使用\xdef
(这会破坏重音字符)。
由于写入操作发生在循环周期内\immediate
,因此也不需要全局定义。您只需\pgfplotsretval
以不同的(本地)名称保存即可。
\begin{filecontents}[overwrite]{\jobname-original.csv}
Z; Symbol; Name
2; He; Helium
41; Mo; Molybdän
\end{filecontents}
\documentclass{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\pgfplotstableread[col sep=semicolon, header=true]{\jobname-original.csv} {\psetable}
% Methode % https://tex.stackexchange.com/a/598981/46023
\makeatletter
\providecommand\protected@iwrite[3]{%
\begingroup
#2%
\let\protect\@unexpandable@protect
\edef\reserved@a{\immediate\write#1{#3}}%
\reserved@a
\endgroup
\if@nobreak\ifvmode\nobreak\fi\fi
}
\newcommand{\mywrite}[2]{\protected@iwrite#1{}{#2}}%
\makeatother
\begin{document}
\newwrite\out
\immediate\openout\out=\jobname.csv
\foreach[count=\n from 0] \row in {0,1}{%%
% In:
\pgfplotstablegetelem{\row}{Z}\of{\psetable}%
\let\Z\pgfplotsretval
\pgfplotstablegetelem{\row}{Symbol}\of{\psetable}%
\let\Symbol\pgfplotsretval
\pgfplotstablegetelem{\row}{Name}\of{\psetable}%
\let\Name\pgfplotsretval
% Out:
\mywrite\out{\Z; \Symbol; \Name}% works!
}
\immediate\closeout\out
%\input{out.csv}
% Target in:
\pgfplotstableread[col sep=semicolon, header=false]{\jobname.csv}{\mytable}
\pgfplotstabletypeset[string type]{\mytable}
\end{document}
(文件名已更改以避免破坏我的文件。)
写入文件的内容是
2; He; Helium
41; Mo; Molybdän
正如预期的那样。
一个expl3
版本。
\begin{filecontents}[overwrite]{\jobname-original.csv}
Z; Symbol; Name
2; He; Helium
41; Mo; Molybdän
\end{filecontents}
\documentclass{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\pgfplotstableread[col sep=semicolon, header=true]{\jobname-original.csv} {\psetable}
\ExplSyntaxOn
\NewDocumentCommand{\startwritingfile}{mm}
{% #1 = output stream, #2 = file name
\iow_new:N #1
\iow_open:Nn #1 { #2 }
}
\NewDocumentCommand{\finishwritingfile}{m}
{% #1 = output stream
\iow_close:N #1
}
\NewDocumentCommand{\mywrite}{mm}
{% #1 = output stream, #2 = tokens to write
\iow_now:Nx #1 { \text_expand:n { #2 } }
}
\ExplSyntaxOff
\begin{document}
\startwritingfile{\out}{\jobname.csv}
\foreach[count=\n from 0] \row in {0,1}{%%
% In:
\pgfplotstablegetelem{\row}{Z}\of{\psetable}%
\let\Z\pgfplotsretval
\pgfplotstablegetelem{\row}{Symbol}\of{\psetable}%
\let\Symbol\pgfplotsretval
\pgfplotstablegetelem{\row}{Name}\of{\psetable}%
\let\Name\pgfplotsretval
% Out:
\mywrite\out{\Z; \Symbol; \Name}% works!
}
\finishwritingfile{\out}
%\input{out.csv}
% Target in:
\pgfplotstableread[col sep=semicolon, header=false]{\jobname.csv}{\mytable}
\pgfplotstabletypeset[string type]{\mytable}
\end{document}
答案3
正如一些评论所指出的那样:
LuaLaTeX
无需任何特殊方法即可让它发挥作用。
% arara: lualatex
\begin{filecontents}[overwrite]{originaltable.csv}
Z; Symbol; Name
2; He; Helium
41; Mo; Molybdän
\end{filecontents}
\documentclass{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\pgfplotstableread[col sep=semicolon, header=true]{originaltable.csv} {\psetable}
\begin{document}
\newwrite\out
\immediate\openout\out=out.csv
\foreach[count=\n from 0] \row in {0,1}{%%
% In:
\pgfplotstablegetelem{\row}{Z}\of{\psetable}
\xdef\Z{\pgfplotsretval}%
\pgfplotstablegetelem{\row}{Symbol}\of{\psetable}%
\xdef\Symbol{\pgfplotsretval}%
\pgfplotstablegetelem{\row}{Name}\of{\psetable}%
\xdef\Name{\pgfplotsretval}%
% Out:
\immediate\write\out{\Z; \Symbol; \Name}% does not work :(
}%%
\immediate\closeout\out
%\input{out.csv}
% Target out:
\pgfplotstableread[col sep=semicolon, header=false]{out.csv}{\mytable}
\pgfplotstabletypeset[string type]{\mytable}
\end{document}