#
当我在命令和环境中使用井号/数字符号/散列符号时,这指的是参数。然而,不应该\detokenize{#}
让它不是一个论点?
情况
磅号可以作为日志文件中很好的分隔符。
例子
尝试取消注释第二个\detokenize
以得到错误。
\documentclass{article}
\usepackage{fontspec}% compile with xelatex
\newenvironment{detokenizetest}[1]
{% firstoftwo
\detokenize{##############################################################################}%
%\detokenize{##BEGIN#######################################################################}% uncommenting this causes a compile error
}%
{% secondoftwo
}%
\begin{document}
\null
\end{document}
错误输出
仅当取消注释包含 的行时才会发生此错误BEGIN
。
! Illegal parameter number in definition of \detokenizetest.
<to be read again>
}
l.9 }
%
?
答案1
由于#
类别代码为 6,它在 TeX 中具有非常特殊的含义,因为它用于表示宏定义中的参数。
TeX 的规则告诉我们,当你想店铺宏的替换文本中的a #
,需要将其加倍。
在处理宏定义的替换文本时,单个后面#
必须跟一个数字(1 到 9),表示指向相应参数的指针,而##
将存储为#
。这是允许类似
\def\foo{\def\baz##1{-##1-}}
因此,替换文本和调用\foo
将定义为单参数宏。\def\baz#1{-#1-}
\foo
\baz
\detokenize
替换文本中的原语将完成其工作当宏被调用和展开时,在定义时不会,除非使用完成定义\edef
,它将首先执行完全扩展,然后将替换文本存储在内存中。
请注意,当你这样做时\meaning\foo
(假设上述定义),你会看到
macro:->\def \baz ##1{-##1-}
\detokenize
使用相同机制的也会发生同样的情况。因此
\edef\hashmarks{\detokenize{####}}
实际上会在替换文本中看到两个#
,但最终结果将是四个。处理时的标准机制\edef
首先将数量减半#
,然后\detokenize
将其加倍。特别是,你不能以此方式产生奇数个#
。
如果要生成分隔符行,最好使用间接方法,提前制作由#
类别代码 12 组成的所需标记列表。在示例中,我使用了其中三个,只是因为它是一个奇数。
\documentclass{article}
\begingroup\lccode`?=`# \lowercase{\endgroup
\newcommand{\lineofhashsigns}{???}
}
\newenvironment{delimitedtext}
{\par\lineofhashsigns\par}
{\par\lineofhashsigns\par}
\begin{document}
\begin{delimitedtext}
abc
\end{delimitedtext}
\end{document}
\lineofhashsigns
不需要的不同定义\lowercase
是通过更改类别代码:
\catcode`#=12
\newcommand{\lineofhashsigns}{###}
\catcode`#=6
您可以在替换文本中添加任何标记,只要您不希望宏带有参数。
答案2
原\detokenize
语确实意味着#
不被视为参数,而是在扩展时被视为参数。请记住,在正常赋值(\newcommand
在 LaTeX 中,\def
作为 TeX 原语)中不会发生扩展。这里,\newenvironment
执行与完全相同的“仅存储”标记的操作\newcommand
。这意味着我们有通常的 TeX 规则,即在创建宏时,我们必须具有每个存在的匹配参数#
,否则我们必须将#
标记加倍。
由于\newenvironment
最终解析为\def
,我们可以使用来做你想做的事情\edef
:
\edef\detokenizetest#1{%
\detokenize{##############################################################################}%
\detokenize{##BEGIN#######################################################################}%
}
\def\enddetokenizetest{}% As \newenvironment will do this
\show\detokenizetest