4

I know I should probably not want to, but say for the sake of discussion that I wanted to remove braces from a string for some purpose (background, now obsolete). From its package description, stringstrings should be up to the job.

I can't get it to work, though.

\documentclass{article}
\usepackage{stringstrings}

\begin{document}\centering\ttfamily
  \def\teststring{{ab{cd}ef}}%
  \detokenize\expandafter{\teststring} \\
  \convertchar{\teststring}{\{}{} \\
  \convertchar{\detokenize\expandafter{\teststring}}{\{}{} 
\end{document}

enter image description here
Fun output in the first line if you remove \ttfamily, too.

Digging into the documentation of stringstrings some more, I found out that it inserts periods when it does not understand something. Indeed, braces are forbidden in the input:

Cannot use { and } in stringstrings arguments. However, use \LB ... \RB in lieu of { ... }; manipulate string in [e] mode & \retokenize.

How is that supposed to work? I tried this:

\convertchar[e]{\detokenize\expandafter{\teststring}}{\LB}{}%
\retokenize[v]{\thestring}

but that outputs the third line from above.

How can I replace braces in strings? Answers need not use stringstrings.

4

Not with stringstrings, but with either xstring or l3regex.

\documentclass{article}
\usepackage{xstring,xparse,l3regex}

% xstring
\newcommand{\removebraces}[2][\filename]{%
  \StrRemoveBraces{#2}[#1]%
}

\edef\lbracetoken{\string{}
\edef\rbracetoken{\string}}
\newcommand{\dremovebraces}[2][\filename]{%
  % we assume #2 is a detokenized string
  \StrSubstitute{#2}{\lbracetoken}{}[#1]%
  \StrSubstitute{#1}{\rbracetoken}{}[#1]%
}

% l3regex

\ExplSyntaxOn
\NewDocumentCommand{\xremovebraces}{sO{\filename}m}
 {
  \IfBooleanTF{#1}
   {
    \tl_set:NV #2 #3
   }
   {
    \tl_set:Nn #2 { #3 }
   }
  \regex_replace_all:nnN { \{(.*?)\} } { \1 } #2
 }
\ExplSyntaxOff


\begin{document}

xstring:

\removebraces{{file_name.test}.png}
\texttt{\detokenize\expandafter{\filename}}

\edef\test{\detokenize{{file_name.test}.png}}
\dremovebraces{\test}
\texttt{\filename}

\bigskip

l3regex:

\xremovebraces{{file_name.test}.png}
\texttt{\detokenize\expandafter{\filename}}

\edef\test{\detokenize{{file_name.test}.png}}
\xremovebraces*{\test}
\texttt{\filename}

\end{document}

In these macros I assume that there's only one level of inner braces. The macro \removebraces accepts any string, whereas \dremovebraces expects a detokenized one.

For \xremovebraces there's no expectation; the *-variant is used to give a macro as argument.

All four macros take an optional argument, whose default value is \filename, where the final result is stored.

enter image description here

  • Why remove only matching pairs of braces? While this certainly has applications, it's not strictly required here, so I wonder what your thought process was. – Raphael May 28 '15 at 14:08
2

Here's a LuaLaTeX-based solution. It sets up two macros: \replacebraces to replace braces with dots, and \removebraces to remove them entirely.

Remark: If your test string contains characters that are "special" to TeX (other than curly braces, i.e., characters such as $, &, and _), just encase the macros \removebraces and \replacebraces in a \detokenize\expandafter{...} "wrapper" statement in order to "print" the modified strings.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}

%% Lua-side code
\usepackage{luacode} % for "luacode" environment and "\luastring" macro
\begin{luacode}
function replace_braces ( s )
   s = string.gsub (s, "[%{%}]", ".")
   tex.sprint ( s )
end

function remove_braces ( s )
   s = string.gsub (s, "[%{%}]", "")
   tex.sprint ( s )
end   
\end{luacode}

%% TeX-side code
\newcommand{\replacebraces}[1]{%
    \directlua{ replace_braces ( \luastring{#1} )} } 
\newcommand{\removebraces}[1]{%
    \directlua{ remove_braces ( \luastring{#1} )} } 

% Set up a "string" that contains curly braces
\def\teststring{uuu{ab{cd}ef}vvv}
\begin{document}

Test string, curly braces replaced with dots: \replacebraces{\teststring}

Test string, curly braces removed entirely: \removebraces{\teststring}
\end{document}
  • 1
    That's one notch on my "why should I switch to LuaLaTeX?" stick. Thanks! – Raphael May 27 '15 at 17:24

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.