所以我有一个代码,修改自这是用户“ShreevatsaR”的回答,可以使用
\tooltips{...}
该代码对其中的任何字符都非常有用。
例如,对于:
\tooltips{疊音詞疊音詞疊音詞}
只有...代码会卡住标点符号。
代码不是为标点符号设计的,这没问题。因为代码运行了一些字符编码转换,而标点符号不需要这些转换。
但是,问题是,目前我无法编译这样的东西:
\tooltips{疊音詞(疊、音、詞。)疊音詞}
事实上,我必须手动复制和粘贴,直到最终获得命令之外的所有标点符号,并重新初始化非标点符号部分的环境:
\tooltips{疊音詞}(\tooltips{疊}、\tooltips{音}、\tooltips{詞}。)\tooltips{疊音詞}
这有点耗时。有什么方法可以自动完成吗?
请注意,对于这个问题,答案不需要使用特定的\tooltips{
...}
命令。就我而言,你可以用以下命令替换任何命令类型,例如:
从:
\any{疊音詞(疊、音、詞。)疊音詞}
到:
\any{疊音詞}(\any{疊}、\any{音}、\any{詞}。)\any{疊音詞}
此外,中文字符不是必需的。它们可以是任何不在预定义排除项目列表中的内容,例如:
从:
\any{AQ(D、Y、F。)PIOP}
到:
\any{AQ}(\any{D}、\any{Y}、\any{F}。)\any{PIOP}
重点是排除任何标点符号(在本例中(
是 and、
和。
and ))
。
我会满意:
- 答案要么因此排除所有可能的标点符号,无论 Tex 怎样找出这些……
- 或者允许指定标点符号列表的答案(例如,以下示例中的
,
and?
and.
and"
and and )。-
从:
\any{AQ,D?Y.F'-PIOP}
到:
\any{AQ},\any{D}?\any{Y}.\any{F}'-\any{PIOP}
答案1
您可以从 OPmac 使用。它用后面跟有此标点符号的\replacetrings
替换提到的标点符号。然后您可以定义简单的宏,参数用 分隔。&
\anyA
&
\replacestring
当你使用纯 TeX 加 OPmac 时,定义的代码不能直接使用。
\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\bgroup \catcode`!=3 \catcode`?=3
\gdef\replacestrings#1#2{\long\def\replacestringsA##1#1{\def\tmpb{##1}\replacestringsB}%
\long\def\replacestringsB##1#1{\ifx!##1\relax \else\addto\tmpb{#2##1}%
\expandafter\replacestringsB\fi}% improved version <May 2016> inspired
\expandafter\replacestringsA\tmpb?#1!#1% from pysyntax.tex by Petr Krajnik
\long\def\replacestringsA##1?{\def\tmpb{##1}}\expandafter\replacestringsA\tmpb
}
\egroup
\def\any#1{\def\tmpb{#1}%
\replacestrings {,} {&,}%
\replacestrings {.} {&.}%
\replacestrings {'-} {&{'-}}
\replacestrings {'} {&'}%
\replacestrings {(} {&(}%
\replacestrings {)} {&)}%
\replacestrings {?} {&?}%
\expandafter\anyA\tmpb&{}%
}
\def\anyA#1#2{\anyX{#1#2}#3\ifx&\else\expandafter\anyB\fi}
\def\anyB{\futurelet\next\anyC}
\def\anyC{\expandafter\ifx\space\next\space\fi\anyA}
% just for testing:
\def\anyX#1{any[#1]}
\any{AQ,D?Y.F'-PIOP}
% result: any[AQ],any[D]?any[Y].any[F]'-any[PIOP]
\bye
答案2
新的答案——保留标点符号
我知道的唯一按任意字符集拆分文本的方法是\regex_split
使用解释3. 对我来说这是一个可怕的领域。
下面的代码可以产生输出:
从(本质上)以下几行来看:
\Any{A, (B: C. D)}
\Any{A), E, G H(;;,) (B: C. D)}
\Any{abc,a:b::def:f}
\Any{A,A,,AAA}
完整代码如下:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l_word_seq % define a new seqence
\NewDocumentCommand\IterateOverPunctutation{ m m }{
% apply "function" #2 to the "words" in #1 between the punctuation characters
\regex_split:nnN{ ([\(\)\.,;\:\s]+) }{ #1 }\l_word_seq% split word to sequence
\cs_set:Nn \l_map_two:n {
\regex_match:nnTF{ ^[\(\)\.,;\:\s]*$ }{##1}
{##1}% matches a punctuation character or empty string
{#2{##1}}% apply #2 to ##1
}
\seq_map_function:NN\l_word_seq\l_map_two:n% apply \l_map_two to sequence
}
\ExplSyntaxOff
\begin{document}
% make a wrapper for \Any to apply \IterateOverPunctutation
\newcommand\realAny[1]{``\textbf{#1}''\space}% a dummy \Any command
\newcommand\Any[1]{\IterateOverPunctutation{#1}\realAny}
\Any{A, (B: C. D)}
\Any{A), E, G H(;;,) (B: C. D)}
\Any{abc,a:b::def:f}
\Any{A,A,,AAA}
\end{document}
我发现解释3为了避免令人害怕,让我稍微解释一下代码的工作原理。
- 理论上, *正则表达式
([\(\)\.,;\:\s]+)
匹配一个或多个“标点符号”(.,;:)周围的空格。表示[...]
匹配其中任何一个,表示+
它们应该出现一次或多次。我们必须“转义”字符(.:),因为它们在正则表达式中还有其他含义,并且\s
是任何“空格”字符。最后,(...)
使其成为“匹配组”,这意味着稍后会记住它。请参阅l3regex文档以了解更多详细信息。 \regex_split:nnN
将“单词”拆分为由#1
正则表达式中的内容分隔的序列。这里的关键是正则表达式中的匹配组(即标点符号)也会被放入序列中!这意味着我们可以遍历该序列,使用\seq_map_function:NN
并使用\regex_match:nnTF
来打印标点符号或应用于\Any
序列中的“单词”。- 定义
\cs_set:Nn
一个新的宏,应用于序列的每个元素,其中包括标点符号,因为正则表达式中的捕获组(与\cs_new:Nn
此不同,如果命令已准备好定义,则不会抱怨 - 如果“句子”以标点符号结尾,则 中将有一个“空”序列
\l_word_seq
。为了满足此要求,\regex_match
查找^[\(\)\.,;\:\s]*$
,它匹配 0 次或多次“标点符号”,但前提是它是 的全部##1
。也就是说,它接受空字符串或完整的标点符号句子。
原始答案
我将回答评论中给出的问题版本,即\something
对逗号分隔列表的每个元素应用命令。使用\docsvlist
来自电子工具箱包裹。
由于没有 MWe,并且\something
下面的 MWe没有\something
定义\textbf
:
\documentclass{article}
\usepackage{etoolbox}
\begin{document}
\renewcommand*\do[1]{\textbf{#1}}
\docsvlist{A,B,C,D}
\end{document}
空格分隔的列表稍微难一点,可能不值得付出努力。考虑到原始问题中使用了逗号,我认为这没问题。当然,如果\something
用 OP 的命令替换,可能会出错\tooltips
,但在几乎所有情况下,这都是没问题的。
答案3
这似乎有效;首先我们按空格分割输入,然后处理每个项目。
它需要定义\tooltipsA
为执行以下任务的宏真实的与工具提示一起使用,而\tooltip
仅用于处理标点符号的输入。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\tooltipsA}{m}
{
\fbox{#1} % this should be the real action of your \tooltip command
}
\NewDocumentCommand{\tooltip}{m}
{
\seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 }
\seq_clear:N \l_tmpb_seq
\seq_map_function:NN \l_tmpa_seq \vincent_process:n
\seq_use:Nn \l_tmpb_seq { ~ }
}
\cs_new_protected:Nn \vincent_process:n
{
\tl_set:Nn \l_tmpa_tl { #1 }
\regex_replace_all:nnN
{ ( [^\(\)]+? ) ( [,.]+? ) } % <==== Here define your punctuations
{ \c{tooltipsA}\cB\{ \1 \cE\} \2 }
\l_tmpa_tl
\regex_match:nVF { \c{tooltipsA} } \l_tmpa_tl
{
\regex_replace_once:nnN
{ ( \(? ) ( [^\(\)]* ) }
{ \1 \c{tooltipsA}\cB\{ \2 \cE\} }
\l_tmpa_tl
}
\seq_put_right:NV \l_tmpb_seq \l_tmpa_tl
}
\cs_generate_variant:Nn \regex_match:nnF { nV }
\ExplSyntaxOff
\begin{document}
\tooltip{a,b,c.}
\tooltip{abc (d,ef,g.) hij (uuu vvv)}
\end{document}
这里我给出了 的伪定义\tooltipsA
,只是为了显示结果符合预期。
答案4
该listofitems
包可以快速完成该工作。
\documentclass{article}
\usepackage{listofitems,amsmath}
\newcommand\any[1]{\fbox{#1}}
%%%
\let\svany\any
\renewcommand\any[1]{%
\setsepchar{,||?||.||'||-||(||)|| }
\readlist\mylist{#1}%
\foreachitem\i\in\mylist{%
\expandafter\ifx\expandafter\relax\i\else\svany{\i}\fi%
\ifnum\icnt<\mylistlen\relax\mylistsep[\icnt]\fi%
}%
}
%%%
\begin{document}
\any{AQ,D?Y.F'-PIOP}
\any{a,b,c.}
\any{abc (d,ef,g.) hij (uuu vvv)}
\end{document}