
Quiero dividir una cadena delimitada por espacios en partes y generar código para cada parte. Aparentemente, TeX funciona con cadenas delimitadas por comas de forma nativa, así que intenté escribir una adaptación.
\usepackage{xstring}
\makeatletter
\@for\next:=foo,bar,baz\do{X \next Y} \\
\StrSubstitute{foo bar baz}{ }{,} \\
\@for\next:=\StrSubstitute{foo bar baz}{ }{,}\do{X \next Y}
\makeatother
La primera línea de salida de una cadena delimitada por comas es correcta. La segunda línea de salida que muestra una cadena delimitada por espacios que se transforma en la cadena correspondiente delimitada por comas es correcta.
Sin embargo, en la tercera línea, la segunda \@for
, la cadena no se divide.
¿Por qué no y cómo soluciono esto?
Respuesta1
\StrSubstitute
tiene múltiples argumentos opcionales y no se puede expandir, por lo que no es posible usar la salida \StrSubstitute
y volver a introducirla en el flujo de entrada de TeX.
Es posible almacenar el resultado en \StrSubstitute
una macro temporal y utilizar esta macro como entrada para \@for\next
...
\documentclass{article}
\usepackage{xstring}
\begin{document}
\makeatletter
\@for\next:=foo,bar,baz\do{X \next Y} \\
\StrSubstitute{foo bar baz}{ }{,} \\
\StrSubstitute{foo bar baz}{ }{,}[\@stuff]
\@for\next:=\@stuff\do{X \next Y}
\makeatother
\end{document}
Respuesta2
Si el requisito es recorrer una lista separada por espacios, no es necesario reemplazar los espacios por comas y recorrer una lista separada por comas. La implementación de ese reemplazo probablemente ya requiera la capacidad de iterar sobre los espacios.
Por ejemplo, esto itera sobre las palabras separadas por espacios y coloca cada una en un fbox.
\documentclass{article}
\def\zz#1{\zzz#1 \! }
\def\zzz#1 {\ifx\!#1\else\fbox{#1} \expandafter\zzz\fi}
\begin{document}
\zz{foo bar baz}
\end{document}
Respuesta3
El listofitems
paquete puede analizarse en función de una multiplicidad de caracteres especificada, aquí indicada como un espacio y una coma
,
. Por tanto, una definición de \setsepchar
resuelve todos los casos, sin el uso de xstring
. EDITADO para incorporar la solución en la macro \processlist
.
\documentclass{scrartcl}
\usepackage{listofitems}
\setsepchar{ ||,}%
\newcommand\processlist[1]{%
\readlist\mylist{#1}%
\foreachitem\next\in\mylist{X \next Y}%
}
\begin{document}
\processlist{foo,bar,baz}
\processlist{foo bar baz}
\end{document}