Replacing # for use inside \label

we currently use unique IDs inside our documents that can be extended by adding one or more tags. A tag always starts with an hash character eg. MY.REQ.ID.42#TAG1#TAG2

The following code is part of a macro that we use to generate 'nice' looking requirements:

\textbf{#1}\def\@currentlabel{#1}\label{req:#1}

Together with a list where all requirements are listed, \label has problems with the # character inside. So I'm looking for a way to get rid to the character by replacing it with something other, eg. '..' or 'HASH'.

any idea would be appreciated...

\documentclass[a4paper]{scrartcl}
\usepackage[left=2cm,right=2cm,top=2.5cm,bottom=2cm]{geometry}
\setlength\parindent{0pt}

\makeatletter
\newcommand{\req}[2]{%
\begingroup%
\textbf{#1}\def\@currentlabel{#1}\label{req:#1}~#2\newline
\endgroup%
} %

\DeclareNewTOC[%
type=requirement, %
types=requirements, %
name=Anforderung, %
listname={List of Requirements} %
]{lor}
\setuptoc{lor}{chapteratlist}

\begin{document}
\section{Test}
\req{MY.REQ.ID.42}{Lorem ipsum dolor sit amet,...}

\req{MY.REQ.ID.43\#BROKEN}{this requirement is broken,...}

Please have a look at \ref{req:MY.REQ.ID.42} on page~\pageref{req:MY.REQ.ID.42}

\listofrequirements

\end{document}

part of the log file:

(./req_test.aux
! Missing \endcsname inserted.
\#
l.5 ...REQ.ID.43\#BROKEN}{{MY.REQ.ID.43\#BROKEN}{1}}

The control sequence marked <to be read again> should
not appear between \csname and \endcsname.

LaTeX Warning: Label req:MY.REQ.ID.43\#BROKEN' multiply defined.

! Missing \endcsname inserted.
\#
l.5 ...REQ.ID.43\#BROKEN}{{MY.REQ.ID.43\#BROKEN}{1}}

The control sequence marked <to be read again> should
not appear between \csname and \endcsname.

)
• Hi, I'm not sure I follow what you mean. Could you post a minimal example please? – yo' Apr 2 '15 at 10:28
• sure, here we go. – aronadaal Apr 2 '15 at 10:36
• Thanks. Now it makes sense to me. I'll post a solution soon I hope. – yo' Apr 2 '15 at 10:38
• Follow up to Referencing my own command – Johannes_B Apr 2 '15 at 10:50
• Sorry, I think I give up. # is just the worst choice for a char in anything. You can make it working, but it would mean redefining everything in LaTeX. (Or find someone who's a better TeXpert than me). – yo' Apr 2 '15 at 11:10

In your example, you used \# in the \req parameter. If this is not an issue, you can simply redefine locally its meaning when you generate the label. For instance, you can replace \label{req:#1} by {\def\#{REPLACEMENT}\xdef\lbl{req:#1}}\label{\lbl}.

Example:

\documentclass[a4paper]{scrartcl}
\usepackage[left=2cm,right=2cm,top=2.5cm,bottom=2cm]{geometry}
\setlength\parindent{0pt}

\makeatletter
\newcommand{\hashtag}{\#}
\newcommand{\req}[2]{%

\begingroup%
\textbf{#1}{\def\@currentlabel{#1}{\def\#{::}\xdef\lbl{req:#1}}\label{\lbl}}~#2\newline%
\endgroup%
} %

\DeclareNewTOC[%
type=requirement, %
types=requirements, %
name=Anforderung, %
listname={List of Requirements} %
]{lor}
\setuptoc{lor}{chapteratlist}

\begin{document}
\section{Test}
\req{MY.REQ.ID.42}{Lorem ipsum dolor sit amet,...}%
\req{MY.REQ.ID.42\#WORKING}{this requirement is broken,...}

Please have a look at \ref{req:MY.REQ.ID.42} on page~\pageref{req:MY.REQ.ID.42}

Please have a look at \ref{req:MY.REQ.ID.42::WORKING} on page~\pageref{req:MY.REQ.ID.42::WORKING}

\listofrequirements

\end{document}
• thanks for your answer. Well, I have to use the \# inside the document because there will be errors like (! You can't use macro parameter character #' in horizontal mode.) instead. Your code looks quite simple and works properly. – aronadaal Apr 2 '15 at 12:20

Because the simple solution isn't here till now, I put it:

\protected\edef\#{\string#}
• It would be better saying also where one should put this code. – egreg Apr 2 '15 at 13:00
• IMHO, this is clear: in the area where another definitions are:). For example, before \DeclareNewTOC. – wipet Apr 2 '15 at 13:39

Well, this works, but it is a very dirty trick. I hope I'll later manage to comment the code. One thing is sure: it's extremely fragile (and impossible to robustify).

\documentclass[a4paper]{scrartcl}
\usepackage[left=2cm,right=2cm,top=2.5cm,bottom=2cm]{geometry}
\setlength\parindent{0pt}

\makeatletter
\def\req#1#2{%
\begingroup
\catcode\#=13
\makehashexcl
\edef\aron@do@label{\noexpand\label{req:\scantokens{#1\noexpand}}}%
\makehashhash
{\bfseries\scantokens{#1\noexpand}}%
\edef\@currentlabel{\scantokens{#1\noexpand}}%
\aron@do@label
~#2\newline
\aron@do@lor
\endgroup%
}

\def\refreq#1#2{%
\begingroup
\catcode\#=13
\makehashexcl
\edef\aron@do@{\noexpand#1{req:\scantokens{#2\noexpand}}}%
\aron@do@
\endgroup
}

\catcode\#=13
\def\makehashexcl{\def##{!}}
\def\makehashhash{\def##{\char35 }}
\makehashhash
\catcode\#=6

\DeclareRobustCommand\HASH{\char35 }

\makeatother

\DeclareNewTOC[
type=requirement,
types=requirements,
name=Anforderung,
listname={List of Requirements}
]{lor}
\setuptoc{lor}{chapteratlist}

\begin{document}

\section{Test}

\req{MY.REQ.ID.42}{Lorem ipsum dolor sit amet,...}

\req{MY.REQ.ID.43#BROKEN}{this requirement is broken,...}

Please have a look at \ref{req:MY.REQ.ID.42} on page~\pageref{req:MY.REQ.ID.42}

Please have a look at \refreq\ref{MY.REQ.ID.43#BROKEN} on page~\refreq\pageref{MY.REQ.ID.43#BROKEN}

\listofrequirements

\end{document}
• thanks for your answer. I think the code of @TonioElGringo will solve my problem. What do you think? – aronadaal Apr 2 '15 at 12:23

Here I use the \convertchar macro of the stringstrings package to change all occurances of \# into ?, and use that in the label.

\documentclass[a4paper]{scrartcl}
\usepackage[left=2cm,right=2cm,top=2.5cm,bottom=2cm]{geometry}
\usepackage{stringstrings}
\setlength\parindent{0pt}

\makeatletter
\newcommand{\req}[2]{%
\convertchar[q]{#1}{\#}{?}%
\begingroup%
\textbf{#1}\def\@currentlabel{#1}\label{req:\thestring}~#2\newline
\endgroup%
} %

\DeclareNewTOC[%
type=requirement, %
types=requirements, %
name=Anforderung, %
listname={List of Requirements} %
]{lor}
\setuptoc{lor}{chapteratlist}

\begin{document}
\section{Test}
\req{MY.REQ.ID.42}{Lorem ipsum dolor sit amet,...}

\req{MY.REQ.ID.43\#BROKEN\#}{this requirement is broken,...}

Please have a look at \ref{req:MY.REQ.ID.42} on page~\pageref{req:MY.REQ.ID.42}

Please have a look at \ref{req:MY.REQ.ID.43?BROKEN?} on
page~\pageref{req:MY.REQ.ID.43?BROKEN?}

\listofrequirements

\end{document}

• the result looks a bit odd. The Req-ID is now duplicated... once with ? and once with #. – aronadaal Apr 2 '15 at 12:37
• @aronadaal Please see revision. I'm still not quite sure if I've captured your intent. – Steven B. Segletes Apr 2 '15 at 12:50