如何在 pgfplotstable 中使用下划线?

如何在 pgfplotstable 中使用下划线?

我有一个这样的输入文件:

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}

在此处输入图片描述

该解决方案基于以下观察:

  1. 您实际上没有列名,对吗?我添加了header=false导致pgfplotstable将列索引指定为名称(从 0 开始)。

  2. 您的第一列是字符串类型而不是数字,因此我将其添加为样式。

  3. 当然,这是关键部分: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}

相关内容