我有一个这样的输入文件:
some_entry 123
another_entry 456
yet_another_entry 789
我想将其排版为表格:
\pgfplotstabletypeset[col sep=space]{FILENAME}
问题是 LaTeX 似乎将下划线解释为排版下标的命令。
在输入文件中转义下划线不起作用。
答案1
以下是无需类别代码即可解决问题的方案:
\documentclass{standalone}
\usepackage{pgfplotstable}
\begin{document}
\pgfplotstabletypeset[
header=false,
columns/0/.style={
string type,
postproc cell content/.code={%
\pgfplotsutilstrreplace{_}{\_}{##1}%
\pgfkeyslet{/pgfplots/table/@cell content}\pgfplotsretval
},
},
]{
some_entry 123
another_entry 456
yet_another_entry 789
}
\end{document}
该解决方案基于以下观察:
您实际上没有列名,对吗?我添加了
header=false
导致pgfplotstable
将列索引指定为名称(从 0 开始)。您的第一列是字符串类型而不是数字,因此我将其添加为样式。
当然,这是关键部分:LaTeX(不是 pgfplotstable)将 _ 解释为数学模式下标标记。因此:我们可以选择以数学模式呈现整个文本(这不是我们想要的),或者用合适的文本标记替换下标标记。这就是我所做的:我添加了一个应用字符串搜索和替换的后处理器:它用
_
替换\_
。
该方法适用于内联表和输入文件。
请注意,如果列名包含下划线,情况会略有不同 - 在这种情况下,您需要添加column name
以便正确排版列名,我们的示例将变成:
\documentclass{standalone}
\usepackage{pgfplotstable}
\begin{document}
\pgfplotstabletypeset[
columns/A_d/.style={
string type,
column name=$A_d$,
postproc cell content/.code={%
\pgfplotsutilstrreplace{_}{\_}{##1}%
\pgfkeyslet{/pgfplots/table/@cell content}\pgfplotsretval
},
},
]{
A_d B
some_entry 123
another_entry 456
yet_another_entry 789
}
\end{document}
这是可行的,因为数学模式_
实际上是可扩展的,所以它们可以成为列名的一部分。
答案2
\pgfplotstabletypeset[col sep=space,columns/colname1/.style={string type}]{FILENAME}
该文件看起来应如下所示:
colname1 colname2
some\_entry 123
another\_entry 456
yet_another\_entry 789
答案3
这不是一个真正的答案 - 我的动机是@egreg的评论尝试进一步破解,但我失败了,这些是我的笔记;也许它们最终会帮助找到破解/解决方法。
问题是,我有一个.csv
文件,否则它会传递到其他软件中 - 如果不是该死的下划线,它也会传递到 pgfplotstable 中;所以现在我必须退出该文件,并在两个文件中复制相同的数据,我非常不喜欢这样。
因此,我尝试用 Perl 编写一个小的正则表达式脚本,该脚本可以自动转义令人讨厌的字符;然后使用-shell-escape
捕获\write18
输出,以用作输入\pgfplotstableread
;不幸的是,似乎只要我们在其参数中使用标记/宏,\pgfplotstableread
判定它是文件名,而不是内联内容——当然,它会无法找到这样的文件:
!
软件包 pgfplots 错误:无法读取表格文件“etmp”。如果您打算提供内联数据:也许 TeX 搞砸了您的行尾?[...]
或者
!
包 pgfplots 错误:无法读取表文件“var 名称、var 长度、值、[...]
有几次,当我设法将一些东西解释为数据时(虽然不记得怎么做了),这个过程会失败,并显示:
\pgfplotstable@result ...futilensuremath {4}\\GDM_
LANG&\pgfutilensuremath {8...
我无法确切地说,但在这种情况下,它看起来pgfplotstable
实际上是试图从数据中制作命令令牌(可能通过\csname
.. \endcsname
) - 并且因此,我猜改变 catcodes 不会有帮助(从下面的例子可以看出)。
顺便说一句,我唯一成功做过一次但无法重现的事情是让 Latex 在排版表格时以某种方式进入数学模式,在这种情况下它不再被下划线卡住,并且可以编译 - 但是,它将它们解释并排版为下标。有趣的是,这发生在我试图禁用下划线的数学代码(请注意,我并不真正知道数学代码是否可以被禁用;从未找到关于此问题的明确参考 - 只是尝试大幅度地改变它们,看看是否能得到类似的效果;我不能)。
我只想指出pgfplotstable 如何读取数据文件中的 LaTeX 代码?:
pgfplotstable 假设列名不包含可扩展材料。
其处理“显示名称”的方式是使用 \pgfplotstabletypeset 期间使用的列名键明确提供显示名称。
不支持保护列名中的可扩展材料。pgfplotstable 将来不太可能自动支持此类保护(因为无法在 \edef 期间进行保护,而这是访问列的常见用例)。
因此,答案是:不,这通常不受支持。就是这样。
因此,这里是我迄今为止使用的当前无法编译的示例代码(带有注释) - 也许它有助于最终找到解决这个问题的方法:
\documentclass{article}
% \usepackage{tikz} %graphicx
% \usepackage{xcolor} % \pagecolor
% \pagecolor{yellow!15}
\usepackage{pgfplotstable}
\usepackage{tikz}
\usepackage{filecontents}
\usepackage{trace}
\def\csvfile{test.csv}
\begin{filecontents*}{\csvfile}
%# this is my .csv table example; data generated with:
%# $ env | grep 'G\(NO\|DM\)' | column -t -s'=' | awk '// {printf("%s,%s,%s,%s\n", $1,length($1),$2,length($2));}' | sed 's/_/-/g'
var name,var length,value,value length
GNOME-KEYRING-CONTROL,21,/tmp/keyring-JcALFh,19
GDM-KEYBOARD-LAYOUT,19,us,2
GNOME-KEYRING-PID,17,1989,4
GDM_LANG,8,en-DK,5
GDMSESSION,10,gnome-2d,8
GNOME-DESKTOP-SESSION-ID,24,this-is-deprecated,18
\end{filecontents*}
% don't include # here, we need it as comment char? it needs to be, for \x
% don't escape dollar, though? cannot, also it alone is mathmode..
% also escaped \\?
% actually, the easiest is to add noexpand everywhere, instead of just a backslash??
\begin{filecontents*}{escdat.sh}
perl -ne '$_ =~ s/([@#%{}])/\\noexpand$1/g;
$_ =~ s/(\n)/^^J$1/g;
$_ =~ s/(_)/\\noexpand\\$1/g;
print $_' "$1"
\end{filecontents*}
% \let\)\relax % in the end, \{ causes ! TeX capacity exceeded,
% the problem is all these escapes end in commands!
% escape all in a group @#_\$%{} :
% echo -e " # $ % { _ } \n # # % % $ $ # @ " | perl -ne '$_ =~ s/([@#_\$%{}])/\\$1/g; print $_'
% https://tex.stackexchange.com/a/16794/2595
\begingroup\makeatletter\endlinechar=\m@ne\everyeof{\noexpand}
\edef\x{\endgroup\def\noexpand\getEscaped{\@@input|"bash escdat.sh \csvfile" }}\x
% \global\let\textunderscore\relax
% \typeout{\getEscaped}
\gdef\smallcheck{ %
\typeout{BSL '\BSL' \the\catcode\expandafter`\BSL, %
DLR '\DLR' \the\catcode\expandafter`\DLR, %
NHS '\NHS' \the\catcode\expandafter`\NHS, %
}
}
% https://tex.stackexchange.com/a/185740/2595
% https://tex.stackexchange.com/a/69294/2595
\begingroup
\catcode `\|=0
|catcode `|\=11
|catcode `|$=11
|catcode `|#=11
|catcode `|_=11
|gdef|LF{\n} % \LF becomes (ASCII) "\n" (verbatim char!)
|gdef|n{\n} % \n becomes (ASCII) "\n" (verbatim char!)
|gdef|ELF{\\n} % \ELF becomes (ASCII) "\\n" - escaped backslash for shell!
|gdef|BSL{\} %
|gdef|DLR{$} %
|gdef|NHS{#} %
|gdef|USC{_} %
% |xdef|etmp{|getEscaped}
|smallcheck % new catcodes here: BSL '\' 11, DLR '$' 11, NHS '#' 11,
|endgroup
% back to old catcodes here: BSL '\' 0, DLR '$' 3, NHS '#' 6,
\smallcheck
\gdef\textunderscore{}
\edef\etmp{\getEscaped}
\typeout{\etmp}
\traceon
% \begingroup
\global\let\mytable\relax
\edef\tmpcmd{\noexpand\pgfplotstableread[%
col sep=comma,
% hash/number sign # should be comment char by default.
% # is: ASCII 35=0x23 hex
%comment chars={\^^23},
%ignore chars={,\^^24}, % 0x5c=92='\', 0x24=36='$' % bad, ! Improper alphabetic constant. for \uC macro:->\uC ,\$ - backslash?
%comment chars={\#}, % can do without this
ignore chars={\noexpand\\,\noexpand\$,\noexpand\{}, % \BSL, \DLR are: ! Improper alphabetic ...
string replace*={\noexpand\USC}{...}, %nowork % {\_}{+},% nowork
header=true,
% ]{./test.csv}\mytable
]{ ^^J
\# trying a hack \noexpand\\^^J
\etmp
}\noexpand\mytable %
} \tmpcmd
% ! Package pgfplots Error: Could not read table file '" etmp "'. In case you intended to provide inline data: maybe TeX screwed up your end-of-lines? Try `row sep=crcr' and terminate your lines with `\\' (refer to the pgfplotstable manual for details).
% means it is read with \string - no chance to expand a macro inside there
% \endgroup
% with the \edef and traceon:
% \GenericError ...
% \endgroup
% <to be read again>
% \#
% \pgfplotstableread@filename ->"
% \#
% trying a hack \\
% var name,var length,v...
% \pgfplotstableread@openfile ...tableread@filename
% .tex \ifeof \r@pgfplots@re...
% \pgfplotstableread@impl@ ...otstableread@openfile
% \def \pgfplotstableread@im...
% l.95 } \tmpcmd
\begin{document}
\begin{tikzpicture}
\begingroup
\catcode`_=12
\gdef\myunds{_}
\typeout{catcode 1: \the\catcode`_} %catcode 1: 11
\endgroup %
\typeout{catcode 2: \the\catcode`_} % catcode 2: 8
% \typeout{catcode 3: \the\catcode`\myunds} % ! Improper alphabetic constant.
\typeout{catcode 3: \the\catcode\expandafter`\myunds} % catcode 3: 8
\typeout{myunds \myunds}
% https://tex.stackexchange.com/questions/62705/underscore-in-textmode-vs-mathmode
\node[] at (current bounding box.south) {
\resizebox{\textwidth}{!}{
\begingroup%
% \traceon%
\makeatletter\@makeother\_%
\catcode`\_=11 %
\catcode`_=12
\begingroup\lccode`~=`_
\lowercase{\endgroup\let~}\sb
\mathcode`\_="202B %\mathcode`_="8000
\gdef\_{W}
\pgfplotstabletypeset[%
every row/.style={before row={\catcode`_=11\mathcode`\_="202B\def_{+}\relax}},
font=\tiny,
% every row/.style={before row={}},
string replace*={_}{\myunds},%
columns/value/.style={string type},% ,column type={l}
columns/var name/.style={string type},% ,column type={l}
]\mytable
\endgroup
% \makeatother%
}%
};
% for \pgfplotstabletypeset[]\etmp:
% ! Package pgfplots Error: Could not read table file 'var name,var length,value,
% value length
% GNOME-KEYRING-CONTROL,21,/tmp/keyring-JcALFh,19
% so it thinks its a a filename, which it isn't
\end{tikzpicture}
% trace gives:
% \pgfplotstable@result ...futilensuremath {4}\\GDM_
% LANG&\pgfutilensuremath {8...
\end{document}