用另一个字符替换所有出现的某个字符的命令?

用另一个字符替换所有出现的某个字符的命令?

如何定义一个命令,将其参数中某个字符的每个实例替换为另一个特定字符?

例如,我想定义一个命令,通过将 every 替换为来\myreplace{1-2-abc-345}给出输出。1.2.abc.345-.

答案1

使用expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\myreplace}{m}
 {
  \tl_set:Nn \l__maxd_argument_tl { #1 }
  \tl_replace_all:Nnn \l__maxd_argument_tl { - } { . }
  \tl_use:N \l__maxd_argument_tl
 }
\tl_new:N \l__maxd_argument_tl
\ExplSyntaxOff

\begin{document}

\myreplace{1-2-abc-345}

\end{document}

在此处输入图片描述

有什么好处?你可以很容易地用同样的想法来概括你的命令。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\myreplace}{ O{} m }
 {
  \maxd_replace:nn { #1 } { #2 }
 }

\tl_new:N \l__maxd_argument_tl
\cs_new_protected:Npn \maxd_replace:nn #1 #2
 {
  \group_begin:
  \tl_set:Nn \l__maxd_argument_tl { #2 }
  \keys_set:nn { maxd/replace } { #1 }
  \tl_replace_all:NVV \l__maxd_argument_tl \l_maxd_search_tl \l_maxd_replace_tl
  \tl_use:N \l__maxd_argument_tl
  \group_end:
 }
\cs_generate_variant:Nn \tl_replace_all:Nnn { NVV }

\keys_define:nn { maxd/replace }
 {
  search .tl_set:N = \l_maxd_search_tl,
  search .initial:n = { - },
  replace .tl_set:N = \l_maxd_replace_tl,
  replace .initial:n = { . }
 }

\ExplSyntaxOff

\begin{document}

\myreplace{1-2-abc-345}

\myreplace[replace=--]{1-2-abc-345}

\myreplace[search=2,replace=0]{1-2-abc-345}

\end{document}

在此处输入图片描述

答案2

一种方法是\StrSubstitute使用包裹xstring

在此处输入图片描述

代码:

\documentclass{article}
\usepackage{xstring}

\newcommand{\myreplace}[2]{%
    \StrSubstitute{#2}{-}{.}[#1]%
}%

\begin{document}
\myreplace{\NewValue}{1-2-abc-345}
input: 1-2-abc-345 

output: \NewValue

\end{document}

答案3

仅使用 TeX 基元的另一种解决方案:

\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\replacestrings#1#2{%
   \def\tmp##1#1##2\end{\ifx\end##2\end\addto\tmpb{##1}\else\addto\tmpb{##1#2}\tmp##2\end\fi}%
   \expandafter\def\expandafter\tmpb\expandafter{\expandafter}\expandafter\tmp\tmpb#1\end 
}
\def\myreplace#1{\def\tmpb{#1}\replacestrings{-}{.}\tmpb}

\myreplace{1-2-abc-345}

编辑:我会尝试解释怎么运行的. 在我看来,了解 TeX 内部如何运作比不假思索地使用代码或包更有价值。

第一行定义了\addto<macro>{<text>}添加到<macro><text>例如,在\def\a{xx} \addto\a{yy}我们\a定义为之后xxyy

将宏中\replacestrings{<string1>}{<string2>}的所有出现的替换为。首先,宏在第 3 行定义为:<string1>\tmpb<string2>\tmp

\def\tmp#1<string1>#2\end{...}

其次,\tmp执行 ,并将 扩展\tmpb为参数,后跟\end\tmpb(1) 扩展 , (2) 将其设置为空, (3)执行 。这就是第 4 行中\tmp5x 的原因。\expandafter

假设,我们有\def\tmpb{abXXcdXXef}并且运行\replacestring{XX}{YY}。然后\tmp声明为以下伪代码:

\def\tmp#1XX#2\end{if #2 is empty: \addto\tmpb{#1}
                   else: \addto\tmpb{#1YY}
                         \tmp #2\end
                   fi}

然后\tmp aaXXcdXXefXX\end执行,但\tmpb首先将设置为空。使用、\tmp展开#1=aa#2=cdXXefXX由于#2不为空,因此

\addto\tmpb{aaYY} \tmp cdXXefXX\end

执行。因此,\tmpb包括aaYY。第二次运行\tmp扩展#1=cd #2=efXX

\addto\tmpb{cdYY} \tmp efXX\end

现在,\tmpb包括aaYYcdYY。第三次运行的\tmp扩展为#1=ef#2空的

\addto\tmpb{ef}

这给出了结果\tmpb aaYYcdYYef

细心的读者会注意到有一个错误:如果替换的文本以一个结尾X,例如\def\tmpb{aaXXbbX},则<string1>存在XX问题。这是真的,但此线程中的问题要求仅将一个标记替换为一个标记。实际\replacestrings(例如,在 OPmac 中使用)执行了更多步骤:在替换文本的末尾添加特殊标记,然后进行替换,然后删除此特殊标记。

答案4

我想定义一个命令\myreplace{1-2-abc-345}1.2.abc.345通过将每个-命令替换为.

这是一个基于LuaLaTeX的解决方案,它利用了Lua强大的gsub字符串功能。

在此处输入图片描述

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode}
\begin{luacode}
function myreplace ( s ) 
   return ( unicode.utf8.gsub ( s , "-", "." ) )
end
\end{luacode}
\newcommand\myreplace[1]{\directlua{myreplace(\luastringN{#1})}}

\begin{document}
\myreplace{1-2-abc-345}
\end{document}

相关内容