如何进行多个字符串替换?

如何进行多个字符串替换?

我想转义 URL 路径以获得浏览器等也应用的百分比转义。为此,我尝试执行以下操作(注释掉的行是为了显示我在这里的目标):

\documentclass[a5paper]{article}
\usepackage{xstring}

\begin{document}

\newcommand{\urlescape}[1]{{%
  \def\x{\StrSubstitute{#1}{\%}{\%25}}%
  \def\x{\StrSubstitute{\x}{/}{\%2F}}%
  % \def\x{\StrSubstitute{\x}{\&}{\%26}}%
  % \def\x{\StrSubstitute{\x}{ }{\%20}}%
  % \def\x{\StrSubstitute{\x}{\$}{\%24}}%
  % \def\x{\StrSubstitute{\x}{+}{\%2b}}%
  % \def\x{\StrSubstitute{\x}{,}{\%2c}}%
  % \def\x{\StrSubstitute{\x}{:}{\%3a}}%
  % \def\x{\StrSubstitute{\x}{;}{\%3b}}%
  % \edef\x{\StrSubstitute{\x}{=}{\%3d}}%
  % \def\x{\StrSubstitute{\x}{?}{\%3f}}%
  % \def\x{\StrSubstitute{\x}{@}{\%40}}%
  % \def\x{\StrSubstitute{\x}{"}{\%22}}%
  % \def\x{\StrSubstitute{\x}{<}{\%3c}}%
  % \def\x{\StrSubstitute{\x}{>}{\%3e}}%
  % \def\x{\StrSubstitute{\x}{\#}{\%23}}%
  % \def\x{\StrSubstitute{\x}{\{}{\%7b}}%
  % \def\x{\StrSubstitute{\x}{\}}{\%7d}}%
  % \def\x{\StrSubstitute{\x}{|}{\%7c}}%
  % \def\x{\StrSubstitute{\x}{\^}{\%5e}}%
  % \def\x{\StrSubstitute{\x}{\~}{\%7e}}%
  % \def\x{\StrSubstitute{\x}{[}{\%5b}}%
  % \def\x{\StrSubstitute{\x}{]}{\%5d}}%
  % \def\x{\StrSubstitute{\x}{\`}{\%60}}%
  \x}}

\urlescape{abcd/efgh\%foo\#bar baz}

\end{document}

错误消息

然而,这是行不通的;我得到

! Use of \@xs@StrSubstitute@@ doesn't match its definition.
\kernel@ifnextchar ...rved@d =#1\def \reserved@a {
                                                  #2}\def \reserved@b {#3}\f...
l.35 \urlescape{abcd/efgh\%foo\#bar baz}

所以我想,TeX 书中有个奇怪的\edef东西,让我们尝试一下:

\newcommand{\urlescape}[1]{{%
  \def\x{\StrSubstitute{#1}{\%}{\%25}}%
  \edef\x{\StrSubstitute{\x}{/}{\%2F}}%
...

但现在我得到了以下令我困惑的信息:

! Argument of \reserved@a has an extra }.
<inserted text>
                \par
l.35 \urlescape{abcd/efgh\%foo\#bar baz}

我搜索了解决方案和问题,发现了几个提示,其中混合了复杂的魔法药水组合\noexpand\unexpanded遗憾的是,我无法从这些解决方案中提取对我有用的咒语(我现在可能已经足够清楚地表明,对我而言,使用 TeX 更多的是一门艺术而不是一门科学)。

请不要犹豫地指出一个可以做到这一点的包 - URL 转义 - 但我认为如何在 LaTeX 中对字符串执行多次替换的问题是一个更普遍的兴趣,我相信我会经常需要这样的东西。

更新

解释:由于上面的列表太长,所以提出了这个问题;简单的答案是,我从http://perishablepress.com/stop-using-unsafe-characters-in-urls/

在更具体的用例中,根据语义和环境,减少枚举是可能的,也可能是可取的。至于语义,无论您检索http://example.com/foo/bar#baz或,它通常会有所不同http://example.com/foo%2Fbar%23baz;在这样的 URL 中是否转义/和/或#本身是不可预测的,因此我从一个相当大的列表开始。

答案1

你是\x根据自身来定义的,这不是一件好事。你宁愿将中间结果存储在临时宏中,这样xstring就可以使用尾随的可选参数。

在进行第一次替换后存储参数,然后对存储的字符串进行操作。还有一个需要注意的扩展问题:最好的方法是压制 xstring扩展并只手动执行一项:

\documentclass[a5paper]{article}
\usepackage{xstring}

\newcommand{\urlescape}[1]{{%
  \noexpandarg % suppress expansions made by xstring
  \StrSubstitute{#1}{\%}{\%25}[\x]% first step
  \expandafter\StrSubstitute\expandafter{\x}{/}{\%2F}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{\&}{\%26}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{ }{\%20}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{\$}{\%24}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{+}{\%2b}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{,}{\%2c}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{:}{\%3a}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{;}{\%3b}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{?}{\%3f}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{@}{\%40}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{"}{\%22}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{<}{\%3c}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{>}{\%3e}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{\#}{\%23}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{\{}{\%7b}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{\}}{\%7d}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{|}{\%7c}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{\^}{\%5e}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{\~}{\%7e}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{[}{\%5b}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{]}{\%5d}[\x]%
  \expandafter\StrSubstitute\expandafter{\x}{\`}{\%60}[\x]%
  \x}}

\begin{document}

\urlescape{abcd/efgh\%foo\#bar baz}

\end{document}

在此处输入图片描述

一些语法糖可能会更好:

\documentclass[a5paper]{article}
\usepackage{xstring}

\newcommand{\urlescapestep}[2]{%
  \expandafter\StrSubstitute\expandafter{\x}{#1}{#2}[\x]%
}
\newcommand{\urlescape}[1]{{%
  \noexpandarg % suppress expansions made by xstring
  \StrSubstitute{#1}{\%}{\%25}[\x]% first step
  \urlescapestep{/}{\%2F}%
  \urlescapestep{\&}{\%26}%
  \urlescapestep{ }{\%20}%
  \urlescapestep{\$}{\%24}%
  \urlescapestep{+}{\%2b}%
  \urlescapestep{,}{\%2c}%
  \urlescapestep{:}{\%3a}%
  \urlescapestep{;}{\%3b}%
  \urlescapestep{?}{\%3f}%
  \urlescapestep{@}{\%40}%
  \urlescapestep{"}{\%22}%
  \urlescapestep{<}{\%3c}%
  \urlescapestep{>}{\%3e}%
  \urlescapestep{\#}{\%23}%
  \urlescapestep{\{}{\%7b}%
  \urlescapestep{\}}{\%7d}%
  \urlescapestep{|}{\%7c}%
  \urlescapestep{\^}{\%5e}%
  \urlescapestep{\~}{\%7e}%
  \urlescapestep{[}{\%5b}%
  \urlescapestep{]}{\%5d}%
  \urlescapestep{\`}{\%60}%
  \x}}

\begin{document}

\urlescape{abcd/efgh\%foo\#bar baz}

\end{document}

相关内容