我对 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 位引擎和0x110000
Unicode 引擎(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
都是等效的,并为字符分配a
catcode 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 作为第二列的分隔符,仅作为示例(网站很可能会将它们转换为空格)。
当然,这很粗糙。但是,由于有诸如datatool
或cvssimple
之类的软件包可以做得更好,所以我认为没有必要重新发明轮子。
答案2
我觉得你的生活变得复杂了,你真正需要的是“读取一个文本文件并制作一个表格”。
有许多软件包可以做到这一点。在下面的 MWE 中,你可以找到一些示例csvsimple
和pgfplotstable
,但还有其他的:datatool
功能更强大,即使可能不适合初学者。我建议您阅读他们的文档,然后把\catcode
s 留给 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{}%
\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}