Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In Pass a command as argument for another command, a notion of invoking TeX macros as methods was described. In my case, I'm attempting to use arguments within the call structure. My example below uses two passes of \StrSubstitute to replace characters that I want to modify:

\usepackage{xstring} % for StrSubstitute

\newcommand*{\changeslash}[1] {%
    \StrSubstitute{#1}{/}{5c}%
}
\newcommand*{\changedollars}[1] {%
    \StrSubstitute{#1}{\$}{24}%
}
\newcommand*{\changeboth}[1] {%
    \changeslash{\changedollars{#1}}%
}

I've experimented with adding \expandafter in different places, but this problem has me stumped.

share|improve this question
    
Hi baitisj Welcome to TeX.SE! I edited your question just to make the link more descriptive, if you'd prefer it your way, feel free to roll back :) –  cmhughes Sep 30 '12 at 18:51
    
Thank you, for both the welcome, and for the edit, cmhughes! As a new user of LaTeX (and of TeX.SE), I'm grateful. –  baitisj Oct 1 '12 at 3:35
add comment

3 Answers 3

up vote 7 down vote accepted

enter image description here

xstring replacements do not work by expansion, but they need the input string to be expanded, thus adding \expandafter doesn't really help. You need to use the optional argument so that the string with the replacement is stored in a temporary macro, then you can use \expandafter to expand that macro to pass to the second call. In addition as it fully expands its input in a way not entirely consistent with LaTeX \protect mechanism I needed to make \$ e-tex protected.

\documentclass{article}

\usepackage{xstring} % for StrSubstitute

\let\olddollar\$
\protected\def\${\olddollar}


\newcommand*{\changeslash}[1] {%
    \StrSubstitute{#1}{/}{5c}[\temp]%
}
\newcommand*{\changedollars}[1] {%
    \StrSubstitute{#1}{\$}{24}[\temp]%
}
\newcommand*{\changeboth}[1] {%
  \changedollars{#1}%
  \expandafter\changeslash\expandafter{\temp}%
}


\begin{document}


\changeslash{aaa/b\$bb}\temp


\changedollars{aaa/b\$bb}\temp


\changeboth{aaa/b\$bb}\temp

\end{document} 
share|improve this answer
    
This worked beautifully, and I think it's clear enough that a newbie like me can begin to understand what is going on. I really appreciate the help, Dr. Carlisle! –  baitisj Oct 1 '12 at 21:26
add comment

The problem seems to rely in two settings that you should apply:

\noexpandargs
\exploregroups

If I give your definitions and use those declarations, from

\changeboth{A/B\$C}

I get that LaTeX prints

A5cB24C

which seems what you're expecting. However you'll have no way to retrieve the modified string. If instead you want to store the result in a macro for later usage, a different approach should be used.

\documentclass{article}
\usepackage{xstring} % for StrSubstitute

\newcommand*{\changeslash}[1]{%
    \StrSubstitute{#1}{/}{5c}[\temp]%
}
\newcommand*{\changedollars}[1]{%
    \StrSubstitute{#1}{\$}{24}[\temp]%
}
\newcommand*{\changeboth}[1]{%
  \changedollars{#1}%
  \expandafter\changeslash\expandafter{\temp}%
}

\begin{document}
\noexpandarg
\changeboth{A/B\$C}

\show\temp
\end{document}

This will produce no output, but TeX will print on the terminal

> \temp=macro:
->A5cB24C.
l.18 \show\temp

and you can freely use the changed string. Here \exploregroups is not needed.


A different approach uses LaTeX3 features.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% Document commands
\NewDocumentCommand{\changeslash}{ m }
 {
  \baitisj_change_slash:n { #1 }
 }
\NewDocumentCommand{\changedollars}{ m }
 {
  \baitisj_change_dollars:n { #1 }
 }
\NewDocumentCommand{\printchangedstring}{}
 {
  \tl_use:N \l_baitisj_string_tl
 }
\NewDocumentCommand{\changeboth}{ m }
 {
  \baitisj_change_dollars:n { #1 }
  \baitisj_change_slash:V \l_baitisj_string_tl
 }

% Variables and functions
\tl_new:N \l_baitisj_string_tl
\cs_new_protected:Npn \baitisj_change_slash:n #1
 {
  \tl_set:Nn \l_baitisj_string_tl { #1 }
  \tl_replace_all:Nnn \l_baitisj_string_tl { / } { 5c }
 }
\cs_new_protected:Npn \baitisj_change_dollars:n #1
 {
  \tl_set:Nn \l_baitisj_string_tl { #1 }
  \tl_replace_all:Nnn \l_baitisj_string_tl { \$ } { 24 }
 }
\cs_generate_variant:Nn \baitisj_change_slash:n { V }

\ExplSyntaxOff

\begin{document}

\changeboth{A/B\$C}
\printchangedstring

\end{document}

The scheme for extending this to more substitutions seems clear. It depends on your application using \printchangedstring or using the modified string in other ways.

Note In any case (xstring or xparse method), if you need to change the literal $ into 24, don't use \$, but simply $.

share|improve this answer
add comment

Citing from the xstring documentation explains why your approach does not work:

When full expansion mode is activated with \fullexpandarg, arguments are expanded with an \edef before they are read by the macro.

The macros of this package are not purely expandable, i.e. they cannot be put in the argument of an \edef. Nestling macros is not possible neither.

So this probably does not really help you, but you might have something to look for. It might be easier to help you from here on, if you would state a question.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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