如何将字符重新定义为表格中的对齐制表符

如何将字符重新定义为表格中的对齐制表符

我对 LaTex 有很好的了解,但我花了一段时间挖掘有关 catcode 的信息,但由于它们不太为人所知,所以我还没有看到任何可以帮助解决我的问题的适用示例。

对于那些熟悉数据表实验的人来说,您可能知道将数据以数字形式存储的标准方法是使用表格,以制表符或空格分隔,并输入换行符。这就是许多数据处理程序读取和写入数据的方式。

因此,如果我想在 LaTex 中输入数据,我必须重新格式化数据表,以在列之间添加“与”符号,并在行尾添加双反斜杠。有没有一种直接的方法来创建一个新环境,重新定义空格、制表符和双反斜杠,插入一个表格环境,然后撤消重新定义,这样它们就不会对其余代码产生任何影响,比如

\newenvironment{datatable}[2]  
\catcode{10}=\catcode{4} 
% catcode 10 is spaces and tabs, catcode 4 is an ampersand 

\catcode{5}=\\ % catcode 5 is the return character
% I haven't a clue how to define it as a double-backslash   

\begin{tabular}{#1}  
   \#2  
\end{tabular}  
% I have no idea how I would undo the definitions from above, because if I said   
\catcode{10}=\catcode{10} 
% I'm not sure it would make any sense
% catcode 10 already points to catcode 4
% and I haven't seen anyone use an undo command for catcodes yet 

\catcode{10}=\catcode{4} 
% catcode 10 is spaces and tabs, catcode 4 is an ampersand 

\catcode{5}=\\ 
% catcode 5 is the return character, I haven't a clue how to define it
% as a double-backslash   

\begin{tabular}{#1}  
   #2  
\end{tabular}  
% I have no idea how I would undo the definitions from above
% because if I said   
\catcode{10}=\catcode{10} 
% I'm not sure it would make any sense
% catcode 10 already points to catcode 4
% and I haven't seen anyone use an undo command for catcodes yet 

希望我清楚自己想要做什么,但实际上我只是想更好地理解重新定义 catcode,然后撤消重新定义。希望这个问题也能帮助其他 Tex 用户。谢谢你的帮助!

编辑:
该解决方案不需要使用 catcode。就我而言,我需要能够在 overleaf.com(它只是一个在线 latex 编辑器和编译器)上实现该解决方案,但除此之外,我没有任何限制。

答案1

TeX 维护着猫码数组;在 8 位引擎和0x110000Unicode 引擎(XeTeX 和 LuaTeX)中,此数组的长度为 256(从 0 开始索引)。数组中的每个条目应为 4 位数字。

您可以通过以下形式的声明来分配条目

\catcode<number> = <4-bit number>

=和其周围的空格是可选的);第一个<number>必须在允许的范围内,即对于 8 位引擎(Knuth TeX,pdftex)为 0-255,对于 Unicode 引擎为 0-1114111。

如果在非赋值上下文中使用,则\catcode<number>返回数组中的相应条目。例如,\the\catcode`a返回 11(在标准设置下)。

数字可以采用标准 TeX 方式之一输入:十进制表示的整数、八进制数、十六进制数或字符代码:

\catcode 97 = 11
\catcode '141 = 11
\catcode "61 = 11
\catcode `a = 11
\catcode `\a = 11

都是等效的,并为字符分配acatcode 11;更严格地说,它们将数字 11 分配给猫码索引为 97 的数组。<number>也可以是返回上下文中的数字的任何内容(计数器的值、标记\chardef\mathchardef标记\numexpr、内部数组条目)。此外,赋值中的右侧可以以不同的格式表示。例如

\catcode`a=\catcode`b

将分配a与 相同的类别代码b(无论 的当前类别代码是什么)b。常见的习语是\catcode<number>=\active,其中\active\chardef值为 13 的标记。

因此,你的\catcode{10}=\catcode{4}语法是错误的。请注意,如果不循环遍历数组,就无法判断“将类别代码 10 的所有字符更改为类别代码 4”;在 8 位引擎中

\count255=0
\loop\ifnum\count255<256
  \ifnum\catcode\count255=10 \catcode\count255=4 \fi
  \advance\count255 by 1
\repeat

会将类别代码 10 的字符更改为类别代码 4 的字符。

当 TeX 在标记化阶段,解释输入并从中形成标记,它将相应的类别代码附加到字符标记上。

让我们开始解决你的问题。你想输入一个文件,但要为一些字符分配不同的类别代码,即制表符和空格,同时将行尾解释为\\。让我们使用如下语法

 \maketabularfromfile{<table specs>}{<filename>}

这是一个可能的代码:

\begin{filecontents*}{\jobname.dat}
a   b c
1   2 3
4   5 6
\end{filecontents*}

\documentclass{article}

\makeatletter
\newcommand{\maketabularfromfile}[2]{%
  % confine the changes
  \begingroup
  \catcode`\ =4   % space is column separator
  \catcode`\^^I=4 % tab is column separator
  \catcode`\^^M=\active % end-of-line is active
  \begingroup\lccode`~=`\^^M \lowercase{\endgroup\def~}{\\}%
  \begin{tabular}{#1}
  \@@input #2 % use the primitive \input
  \end{tabular}
  \endgroup
}
\makeatother

\begin{document}

\maketabularfromfile{ccc}{\jobname.dat}

\end{document}

我使用<TAB>s 作为第二列的分隔符,仅作为示例(网站很可能会将它们转换为空格)。

在此处输入图片描述

当然,这很粗糙。但是,由于有诸如datatoolcvssimple之类的软件包可以做得更好,所以我认为没有必要重新发明轮子。

答案2

我觉得你的生活变得复杂了,你真正需要的是“读取一个文本文件并制作一个表格”。

有许多软件包可以做到这一点。在下面的 MWE 中,你可以找到一些示例csvsimplepgfplotstable,但还有其他的:datatool功能更强大,即使可能不适合初学者。我建议您阅读他们的文档,然后把\catcodes 留给 egreg & Co。

我已经在 Overleaf 上创建了我的示例,使用了常用的 pdfLaTeX 编译器。

\documentclass{article}

\usepackage{booktabs}
\usepackage{siunitx}
\usepackage{csvsimple}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.14}
% you can set some option for all your table if you write this 
\pgfplotstableset{string type, 
    every head row/.style={before row=\toprule,after row=\midrule},
    every last row/.style={after row=\bottomrule}}

\usepackage{filecontents}% only needed to create the csv in this example
% the following filecontents* environments are needed only to create the text files, you don't need the if you already have yourfile....dat
\begin{filecontents*}{yourfilecommasep.dat}
Name,Surname,Length,Gender
Paulinho,van Duck,.56,M
Paulette,de la Quack,.52,F
\end{filecontents*}
\begin{filecontents*}{yourfilespacesep.dat}
Name Surname Length Gender
Paulinho {van Duck} .56 M
Paulette {de la Quack} .52 F
\end{filecontents*}

\begin{document}
\verb|pgfplotstable| accepts space, tab, comma, semicolon, colon, braces, and ampersand as 
separators.

\begin{center}
\pgfplotstabletypeset[
    col sep=space, 
    ]
    {yourfilespacesep.dat}
\end{center}

With \verb|\pgfplotstabletypeset|, you don't even need a file, you can type your data directly.

\begin{center}
\pgfplotstabletypeset[
    col sep=space, 
    ]
    {
    Name Surname Length Gender
    Paulinho {van Duck} .56 M
    Paulette {de la Quack} .52 F
    }
\end{center}

\verb|csvsimple| accepts comma (the default), semicolon, pipe, and tab as separators.

Here I also merged the two colums "Name" and "Surname", and inverted the two colums "Gender" and "Length":
\begin{center}
\begin{tabular}{
    lcS[table-format=1.2,round-mode=places]}
    \toprule
    Ducks and drakes & Gender & {Length} \\
    & & {(\si{\metre})} \\
    \midrule
    \csvreader[head to column names,
        late after line=\\]{yourfilecommasep.dat}{}%
        {\Name\ \Surname & \Gender & \Length}
    \bottomrule
\end{tabular}
\end{center}

\end{document}

在此处输入图片描述

答案3

更改 catcode 总是有点棘手,尤其是在有空格的情况下,并且如果此处的输入可能也包含带空格的括号项目。

因此我只更改了行尾的 catcode。

我在这里说明的是内联输入,如果数据在外部文件中,则需要小的变体。但无论如何,有这样的包,当然这里的方法只是几行宏。

\documentclass{article}

\usepackage{array}
\usepackage{booktabs}

\makeatletter
\def\mytabular@end{\end{mytabular}}
\def\mytabular@parse#1 %
{%
  \if\relax\detokenize{#1}\relax
    \g@addto@macro\mytabular@line{\\}%
    \xdef\mytabular@tabular{%
       \unexpanded\expandafter{\mytabular@tabular}%
       \unexpanded\expandafter\expandafter\expandafter{\mytabular@line}%
       }%
    \expandafter\mytabular@again
  \else
    \g@addto@macro\mytabular@line{&#1}%
    \expandafter\mytabular@parse
  \fi
}%
% some complications to insert toprule but then midrule only once
% after header line
\def\mytabular@newline{%
    \let\mytabular@newline\mytabular@@newline
    \gdef\mytabular@line{\mytabular@atstart\toprule}%
}%
\def\mytabular@@newline{%
    \let\mytabular@newline\mytabular@@@newline
    \gdef\mytabular@line{\mytabular@atstart\midrule}%
}%
\def\mytabular@@@newline{%
    \gdef\mytabular@line{\mytabular@atstart{}}%
}%
\def\mytabular@atstart#1&{#1}%
\def\mytabular@finish{%
    \g@addto@macro\mytabular@tabular{\bottomrule\end{tabular}}%
    \end{mytabular}\mytabular@tabular
}%
\begingroup\catcode`\^^M\active
  \gdef\mytabular@again{\expandafter^^M}%
\endgroup
\def\zzzzzzzzzzzzzzzzzzzzz#1{%
\newenvironment{mytabular}[1]%
  {%
   \gdef\mytabular@tabular{\begin{tabular}{##1}}%
   \obeylines
   \begingroup\lccode`~`\^^M 
   \lowercase{\endgroup\def~####1~}{%
     \def\mytabular@tmp{####1}%
     \ifx\mytabular@tmp\mytabular@end
       \expandafter\mytabular@finish
     \else
       \mytabular@newline%
       \mytabular@parse####1 #1%
     \fi}%
  }%
  {}%
}\zzzzzzzzzzzzzzzzzzzzz{ }%
\makeatother

\begin{document}

\begin{mytabular}{cccc}
    Name Surname Length Gender
    Paulinho {van Duck} .56 M
    Paulette {de la Quack} .52 F
\end{mytabular}

\end{document}

在此处输入图片描述

相关内容