我正在尝试创建一个新环境并将其用作自定义数组(给定的代码有很多变化)。所以我需要阅读\BODY
并\NewEnviron
逐行阅读。我不在乎是否必须用\\
或用空行或其他方式结束行。但我必须逐行阅读它们,而且我不知道在使用环境之前有多少行。
我尝试过这个:
\documentclass{article}
\usepackage{environ}
\usepackage{xstring}
\makeatletter
\long\def\findLength#1{\StrLen{#1}[\temp] The length of ``#1'' is \temp\\}
\NewEnviron{Graph}{\findLength{\BODY}}{}
\makeatother
\begin{document}
\begin{Graph}
test line 1
test line 2
\end{Graph}
\end{document}
但使用全部\BODY
而不是逐行。此外,如果我添加换行符,则#1
的\StrLen
不再是字符串(包含换行符并给出错误)。
我终于设法使用@Bruno Le Floch 的代码在我的新环境中获取第一行这里但我真的不理解那段代码,也不知道该读什么才能理解它,并改变它来接受所有参数。此外,我还不能在行末尾添加 \ 来显示数组行的结束位置... 以下是我现在所拥有的:
\documentclass{article}
\usepackage{environ}% defines `NewEnviron`
\usepackage{xstring}
\makeatletter
\newcommand*{\newlinecommand}[2]{%
\newcommand*{#1}{%
\begingroup%
\escapechar=`\\%
\catcode\endlinechar=\active%
\csname\string#1\endcsname%
}%
\begingroup%
\escapechar=`\\%
\lccode`\~=\endlinechar%
\lowercase{%
\expandafter\endgroup
\expandafter\def\csname\string#1\endcsname##1~%
}{\endgroup#2\par\space}%
}
\makeatother
\makeatletter
\newlinecommand{\findLengthOfRow}{\StrLen{#1}[\temp] The length of ``#1'' is \temp}
\makeatother
\makeatletter
\long\def\findLength#1{\findLengthOfRow{#1}}
\newenvironment{Graph}{\findLength}{}
\makeatother
\begin{document}
\begin{Graph}
test line 1
test line 2
test line 3
\end{Graph}
\end{document}
任何帮助都将不胜感激。我想要的结果是将环境中的行作为参数。(我不知道数组将有多少行。所以不要在新环境中给出具体数量的参数)。
答案1
这使用强大的listofitems
包来解析\BODY
,使用\\
分隔符。
\documentclass[12pt]{article}
\usepackage{listofitems,environ}
\NewEnviron{linebyline}{%
\setsepchar{\\}%
\readlist*\mylines{\BODY}%
\foreachitem\x\in\mylines{Line \xcnt: \x\par}%
The total number of lines is \textbf{\listlen\mylines[]}.
}
\begin{document}
\begin{linebyline}
This is a test\\
of whether\\
I can identify line by line.
\end{linebyline}
\end{document}
这显示了如何进一步逐字逐句地对每一行进行子解析,使用空格作为第二层分隔符:
\documentclass[12pt]{article}
\usepackage{listofitems,environ}
\NewEnviron{linebyline}{%
\setsepchar{\\/ }%
\readlist*\mylines{\BODY}%
\foreachitem\x\in\mylines{Line \xcnt: \x{} (has \listlen\mylines[\xcnt] words,
first/last: ``\mylines[\xcnt,1]/\mylines[\xcnt,-1]'')\par}%
The total number of lines is \textbf{\listlen\mylines[]}.
}
\begin{document}
\begin{linebyline}
This is a test\\
of whether\\
I can identify line by line.
\end{linebyline}
\end{document}
答案2
如果您不关心行是否以 结束\\
(这比使用 更安全\endlinechar
),那么使用 非常简单expl3
。
\documentclass{article}
\usepackage{xparse,environ}
\ExplSyntaxOn
\NewEnviron{Graph}
{
% split the environment's contents into items at the \\ separator
\seq_set_split:NnV \l_koleygr_graph_lines_seq { \\ } \BODY
\begin{enumerate}
% map over the sequence, passing each item to the internal function
\seq_map_function:NN \l_koleygr_graph_lines_seq \koleygr_graph_doline:n
\end{enumerate}
}
\cs_new_protected:Nn \koleygr_graph_doline:n
{
\tl_if_empty:nF { #1 }
{
\item #1
}
}
\ExplSyntaxOff
\begin{document}
Something at the top
\begin{Graph}
Line 1\\
Line 2\\
Line 3
\end{Graph}
Something in between
\begin{Graph}
Line 1\\
Line 2\\
Line 3\\
\end{Graph}
Something at the bottom
\end{document}
我使用了一个虚拟操作在每一行上执行,仅作为示例。如果最后一行以 结尾,则检查是否为空很有用\\
。还有其他可能性:可以简单地检查从 获得的序列中的最后一项是否\BODY
为空。这完全取决于您想对环境的内容做什么。