5

I'm using LaTeX and have a string that I want to remove underscores from, and convert to lower case (in either order). The individual steps work:

\MakeLowercase{AB\_CD} \StrSubstitute{AB\_CD}{\_}{}

yields

ab_cd ABCD

but I get errors for either:

\StrSubstitute{\MakeLowercase{AB\_CD}}{\_}{}

or:

\MakeLowercase{\StrSubstitute{AB\_CD}{\_}{}}

I need to do this in a LaTeX macro, and put the result of this (lower-cased and underscore-stripped) to be usable as an argument to another command, or to be captured into a variable for such use.

Evidently I don't understand how macro substitution really works, but I can't seem to find a good explanation.

  • Welcome to TeX.SX! – Markus Oct 31 '14 at 13:14
  • Thanks Markus! I hope to become proficient with LaTeX and use it for most of my documentation. – Eric Smith Oct 31 '14 at 23:18
1

The stringstrings package is slow and has other problems, but here it can do what you ask:

\documentclass{article}
\usepackage{stringstrings}
\begin{document}
\def\x{AB\_CD}Was: \x

\caselower[e]{\x}
\convertchar[q]{\thestring}{\_}{}
IS: \retokenize[v]{\thestring}
\end{document} 

enter image description here

If you are using T1 encoding, it is easier still.

\documentclass{article}
\usepackage{stringstrings}
\usepackage[T1]{fontenc}
\begin{document}
\def\x{AB\_CD}Was: \x
\caselower[e]{\x}
IS: \convertchar[v]{\thestring}{\_}{}
\end{document} 
  • This solution works pretty well for me. I don't mind if it's slow, but is there somewhere I can read about the "other problems" you referenced? – Eric Smith Nov 1 '14 at 3:32
  • @EricSmith It was one of the earliest packages I wrote, when I knew very little about LaTeX. So I did things very inefficiently. I don't recall the details, but one user reported a conflict with another package. The package has the ability but only in a very limited way, to process macros in its arguments. If you are sticking to manipulating pure text and character macros like \_, etc., it should suffice. – Steven B. Segletes Nov 1 '14 at 14:22
3

Do it in two separate steps:

\documentclass{article}
\usepackage{xstring}

\begin{document}

\StrSubstitute{AB\_CD}{\_}{}[\SUBtemp]\MakeLowercase{\SUBtemp}

\end{document}

enter image description here

  • Is there some fundamental limitation in the way that macros (or commands, or whatever they are) work that requires the use of the temporary variable rather than directly using the result of one as the argument of the other? – Eric Smith Oct 31 '14 at 13:28
  • 1
    @EricSmith Yes: \lowercase doesn't execute what's passed to it and \MakeLowercase adds a layer over it. So \lowercase{\StrSubstitute{AB\_CD}{\_}{}} would work by lowercasing before doing \StrSubstitute, but with \MakeLowercase this is not possible, because basically it scans its input token by token applying \lowercase when needed. – egreg Oct 31 '14 at 15:45
  • I didn't originally state it in the question, but I need to use the output of \MakeLowercase as an argument to something else, either directly or via another temporary variable, and I can't seem to do that. My failed attempt: \newcommand{\munge}[1]{ \StrSubstitute{#1}{\_}{}[\SUBtemp] \def\SUBtemp2{\MakeLowercase{\SUBtemp}} \SomeOtherRandomCommand{\SUBtemp2} } – Eric Smith Nov 1 '14 at 3:08
  • @EricSmith You can't pass the output of \MakeLowercase to any macro: what it produces is just for printing, more or less. Do you really need \MakeLowercase because of accents or are your strings just letters and simple commands like \_? – egreg Nov 1 '14 at 9:26
3

\MakeLowercase expands its argument to get the string to lowercase, but the string replace you are using does not work by expansion. Here though you don't really need a string replace, just locally make \_ expand to nothing.

\documentclass{article}

\begin{document}

{\renewcommand\_{}\MakeLowercase{AB\_CD}}

\end{document}
  • That might be workable, but how to I get the original definition of _ back? For instance, if I use it in a command: \newcommand{\munge}[1]{ \renewcommand\_{}\MakeLowercase{#1} } – Eric Smith Nov 1 '14 at 2:52
  • @EricSmith it is a local redefinition, the original definition is restored at the } at the end of the line shown. Your \newcommand would want {} around the setting as in \newcommand{\munge}[1]{ {\renewcommand\_{}\MakeLowercase{#1}} } – David Carlisle Nov 1 '14 at 9:24
2

With an up-to-date expl3:

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \LowerCase \tl_lower_case:n
\ExplSyntaxOff
\usepackage{xstring}
\begin{document}
\StrSubstitute{\LowerCase{AB\_CD}}{\_}{}
\end{document}

This works because \tl_lower_case:n in expl3 does not use \lowercase and so is expandable (contrast with the comment on egreg's answer).

  • Note that \tl_lower_case:n is experimental both in terms of name and defined behaviour: you may have to adjust your input to allow for any changes in this function. – Joseph Wright Oct 31 '14 at 16:18
  • In principle I like the idea of being forward-looking and using expl3, even if the details may change in the future. However, at the moment I'm struggling with LaTeX 2, so I'm not sure I want to throw LaTeX 3 stuff into the mix. – Eric Smith Nov 1 '14 at 3:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.