2

I'm using a LaTeX macro to sanitize math expressions for label generation. The macro applies \detokenize to the input and then runs a series of \StrSubstitute commands to remove or replace certain symbols.

I expect that a multiline math expression using \begin{aligned}...\end{aligned} should produce the same sanitized result as the inline version. However, the word aligned still appears at the beginning and end of the result from the multiline version — even though I explicitly remove it using:

\StrSubstitute{\temp}{aligned}{}[\temp]

Example output:

Result of sanitize: [alignedPLpBIndexNullRpCommaForallBLpPLpBRpImpCEqxInBMidForallALpPLpARpImpxInARpRpCommaForallBLpPLpBRpImpDEqxInBMidForallALpPLpARpImpxInARpRpVdashCEqDaligned]


Result of sanitize: [PLpBIndexNullRpCommaForallBLpPLpBRpImpCEqxInBMidForallALpPLpARpImpxInARpRpCommaForallBLpPLpBRpImpDEqxInBMidForallALpPLpARpImpxInARpRpVdashCEqD]

Why does the first result still contain aligned? How can I reliably remove it so both variants produce identical output?

My code is below.

\documentclass{article}

\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{xstring}
\usepackage{xparse}

% -------------------------------
% Label-Sanitizer
% -------------------------------

\newcommand{\sanitize}[1]{%
  \edef\temp{\detokenize{#1}}%
  
  \StrSubstitute{\temp}{\string\leftrightarrow}{Equiv}[\temp]%
  \StrSubstitute{\temp}{\string\rightarrow}{Imp}[\temp]%
  \StrSubstitute{\temp}{\string\eqvdash}{Eqvboth}[\temp]%
  \StrSubstitute{\temp}{\string\dashv}{DashV}[\temp]%
  \StrSubstitute{\temp}{\string\vdash}{Vdash}[\temp]%
  \StrSubstitute{\temp}{\string\iff}{Iff}[\temp]%
  \StrSubstitute{\temp}{\string\land}{And}[\temp]%
  \StrSubstitute{\temp}{\string\lor}{Or}[\temp]%
  \StrSubstitute{\temp}{\string\neg}{Neg}[\temp]%

  \StrSubstitute{\temp}{\string\forall}{Forall}[\temp]%
  \StrSubstitute{\temp}{\string\exists}{Exists}[\temp]%
  \StrSubstitute{\temp}{\string\iota}{Iota}[\temp]%

  \StrSubstitute{\temp}{:=}{Defeq}[\temp]%
  \StrSubstitute{\temp}{=}{Eq}[\temp]%
  \StrSubstitute{\temp}{\string\neq}{Neq}[\temp]%
  \StrSubstitute{\temp}{\string\not}{Notin}[\temp]%
  \StrSubstitute{\temp}{\string\in}{In}[\temp]%
  \StrSubstitute{\temp}{\string\subseteq}{Subseteq}[\temp]%

  \StrSubstitute{\temp}{\string\mid}{Mid}[\temp]%

  \StrSubstitute{\temp}{\string_}{Index}[\temp]%
  \StrSubstitute{\temp}{0}{Null}[\temp]%

  \StrSubstitute{\temp}{\string\bigl}{}[\temp]%
  \StrSubstitute{\temp}{\string\bigr}{}[\temp]%
  \StrSubstitute{\temp}{\string\Bigl}{}[\temp]%
  \StrSubstitute{\temp}{\string\Bigr}{}[\temp]%
  \StrSubstitute{\temp}{(}{Lp}[\temp]%
  \StrSubstitute{\temp}{)}{Rp}[\temp]%

  \StrSubstitute{\temp}{\string\begin}{}[\temp]%
  \StrSubstitute{\temp}{\string\end}{}[\temp]%

  \StrSubstitute{\temp}{aligned}{}[\temp]%
  
  \StrSubstitute{\temp}{\string\{}{}[\temp]%
  \StrSubstitute{\temp}{\string\}}{}[\temp]%
  \StrSubstitute{\temp}{\char'\{}{}[\temp]%
  \StrSubstitute{\temp}{\char'\}}{}[\temp]%
  \ExpandArgs{e}\StrSubstitute{\temp}{\string{\iffalse}\fi}{}[\temp]%
  \ExpandArgs{e}\StrSubstitute{\temp}{\iffalse{\fi\string}}{}[\temp]%
  \StrSubstitute{\temp}{\string\,}{}[\temp]%
  \StrSubstitute{\temp}{\string\;}{}[\temp]%
  \StrSubstitute{\temp}{\string\\}{}[\temp]
  \StrSubstitute{\temp}{\string\ }{}[\temp]%
  \StrSubstitute{\temp}{\string&}{}[\temp]%
  \StrSubstitute{\temp}{ }{}[\temp]%

  \StrSubstitute{\temp}{,}{Comma}[\temp]%

}

\makeatletter
\newcommand{\debugsanitize}[1]{%
  \def\tempa{#1}%
  \expandafter\sanitize\expandafter{\tempa}%
  \typeout{Result of sanitize: [\temp]}%
}
\makeatother

\begin{document}

\debugsanitize{
  \begin{aligned}
    &P(B_0),\;
    \forall B\Bigl(P(B)\rightarrow C= \{ x \in B \mid \forall A (P(A) \rightarrow x \in A) \}\Bigr),\\
    &\forall B\Bigl(P(B)\rightarrow D= \{ x \in B \mid \forall A (P(A) \rightarrow x \in A) \}\Bigr)
    \vdash C=D
  \end{aligned}
}

\debugsanitize{P(B_0),\forall B\Bigl(P(B)\rightarrow C= \{ x \in B \mid \forall A (P(A) \rightarrow x \in A) \}\Bigr),\forall B\Bigl(P(B)\rightarrow D= \{ x \in B \mid \forall A (P(A) \rightarrow x \in A) \}\Bigr) \vdash C=D}

\end{document}
1
  • Off-topic: Unless you are using a really old version of pdfLaTeX to compile your document, \usepackage[utf8]{inputenc} is redundant and should be omitted. And, if you're using either XeLaTeX or LuaLaTeX, you shouldn't be running \usepackage[utf8]{inputenc} at all.
    – Mico
    Commented 14 hours ago

1 Answer 1

4

You want to replace a catcode 12 aligned not catcode 11 so as below (although I wouldn't use xstring for this, latex has better functions already in its L3 programming layer

\documentclass{article}

% only if your format is ancient \usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{xstring}
% only if your format is old \usepackage{xparse}

% -------------------------------
% Label-Sanitizer
% -------------------------------

\newcommand{\sanitize}[1]{%
  \edef\temp{\detokenize{#1}}%
  
  \StrSubstitute{\temp}{\string\leftrightarrow}{Equiv}[\temp]%
  \StrSubstitute{\temp}{\string\rightarrow}{Imp}[\temp]%
  \StrSubstitute{\temp}{\string\eqvdash}{Eqvboth}[\temp]%
  \StrSubstitute{\temp}{\string\dashv}{DashV}[\temp]%
  \StrSubstitute{\temp}{\string\vdash}{Vdash}[\temp]%
  \StrSubstitute{\temp}{\string\iff}{Iff}[\temp]%
  \StrSubstitute{\temp}{\string\land}{And}[\temp]%
  \StrSubstitute{\temp}{\string\lor}{Or}[\temp]%
  \StrSubstitute{\temp}{\string\neg}{Neg}[\temp]%

  \StrSubstitute{\temp}{\string\forall}{Forall}[\temp]%
  \StrSubstitute{\temp}{\string\exists}{Exists}[\temp]%
  \StrSubstitute{\temp}{\string\iota}{Iota}[\temp]%

  \StrSubstitute{\temp}{:=}{Defeq}[\temp]%
  \StrSubstitute{\temp}{=}{Eq}[\temp]%
  \StrSubstitute{\temp}{\string\neq}{Neq}[\temp]%
  \StrSubstitute{\temp}{\string\not}{Notin}[\temp]%
  \StrSubstitute{\temp}{\string\in}{In}[\temp]%
  \StrSubstitute{\temp}{\string\subseteq}{Subseteq}[\temp]%

  \StrSubstitute{\temp}{\string\mid}{Mid}[\temp]%

  \StrSubstitute{\temp}{\string_}{Index}[\temp]%
  \StrSubstitute{\temp}{0}{Null}[\temp]%

  \StrSubstitute{\temp}{\string\bigl}{}[\temp]%
  \StrSubstitute{\temp}{\string\bigr}{}[\temp]%
  \StrSubstitute{\temp}{\string\Bigl}{}[\temp]%
  \StrSubstitute{\temp}{\string\Bigr}{}[\temp]%
  \StrSubstitute{\temp}{(}{Lp}[\temp]%
  \StrSubstitute{\temp}{)}{Rp}[\temp]%

  \StrSubstitute{\temp}{\string\begin}{}[\temp]%
  \StrSubstitute{\temp}{\string\end}{}[\temp]%

  \StrSubstitute{\temp}{\detokenize{aligned}}{}[\temp]%
  
  \StrSubstitute{\temp}{\string\{}{}[\temp]%
  \StrSubstitute{\temp}{\string\}}{}[\temp]%
  \StrSubstitute{\temp}{\char'\{}{}[\temp]%
  \StrSubstitute{\temp}{\char'\}}{}[\temp]%
  \ExpandArgs{e}\StrSubstitute{\temp}{\string{\iffalse}\fi}{}[\temp]%
  \ExpandArgs{e}\StrSubstitute{\temp}{\iffalse{\fi\string}}{}[\temp]%
  \StrSubstitute{\temp}{\string\,}{}[\temp]%
  \StrSubstitute{\temp}{\string\;}{}[\temp]%
  \StrSubstitute{\temp}{\string\\}{}[\temp]
  \StrSubstitute{\temp}{\string\ }{}[\temp]%
  \StrSubstitute{\temp}{\string&}{}[\temp]%
  \StrSubstitute{\temp}{ }{}[\temp]%

  \StrSubstitute{\temp}{,}{Comma}[\temp]%

}

\makeatletter
\newcommand{\debugsanitize}[1]{%
  \def\tempa{#1}%
  \expandafter\sanitize\expandafter{\tempa}%
  \typeout{Result of sanitize: [\temp]}%
}
\makeatother

\begin{document}

\debugsanitize{
  \begin{aligned}
    &P(B_0),\;
    \forall B\Bigl(P(B)\rightarrow C= \{ x \in B \mid \forall A (P(A) \rightarrow x \in A) \}\Bigr),\\
    &\forall B\Bigl(P(B)\rightarrow D= \{ x \in B \mid \forall A (P(A) \rightarrow x \in A) \}\Bigr)
    \vdash C=D
  \end{aligned}
}

\debugsanitize{P(B_0),\forall B\Bigl(P(B)\rightarrow C= \{ x \in B \mid \forall A (P(A) \rightarrow x \in A) \}\Bigr),\forall B\Bigl(P(B)\rightarrow D= \{ x \in B \mid \forall A (P(A) \rightarrow x \in A) \}\Bigr) \vdash C=D}

\end{document}

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.