I want to escape URL paths to obtain the percent-escaping that is also applied e.g. by browsers. For this purpose I tried to do the following (out-commented lines are meant to show what I'm aiming here):
\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}
Error messages
However, that wouldn't work; I get
! 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}
So I thought well there's that strange \edef
thingie from the TeX book so let's give it a try:
\newcommand{\urlescape}[1]{{%
\def\x{\StrSubstitute{#1}{\%}{\%25}}%
\edef\x{\StrSubstitute{\x}{/}{\%2F}}%
...
But now I get the following which confuses me:
! Argument of \reserved@a has an extra }.
<inserted text>
\par
l.35 \urlescape{abcd/efgh\%foo\#bar baz}
Solution and question
I searched and I found several hints where intricate combinations of magic potions à la \noexpand
, \unexpanded
got thrown into the mix; sadly, I was unable to extract from those solutions an incantation that would work for me (I've probably made it sufficiently clear by now that using TeX is more of an art than a science to me).
Please do not hesitate to point out a package to do just this — URL escaping — but I think that the question of how to perform multiple replacements on strings in LaTeX is of a more general interest and I'm sure I'll need stuff like that quite often.
Update
Explanation: The question has been raised as the above list is so extensive; the simple answer is that I copy-and-pasted these characters from http://perishablepress.com/stop-using-unsafe-characters-in-urls/.
In a more specific use-case, it will be possible and probably desirable to cut down the enumeration, depending on semantics and environment. as for semantics, it will normally make a difference whether you retrieve http://example.com/foo/bar#baz
or http://example.com/foo%2Fbar%23baz
; whether or not to escape /
and/or #
in such URLs is, as such, unpredictable, so I started out with a fairly maximal list.
\def\x{\StrSubstitute{\x}{...}
doesn't really seem a good start.\def\a{\a}
...\StrSubstitute
of thexstring
documentation. Using the optional (last) argument might be useful.hyperref
or one of Heiko Oberdiek's packages cover this anyway?