Cómo escribir el resultado de una macro en un archivo

Cómo escribir el resultado de una macro en un archivo

Tengo una macro \printauthors que contiene una lista de autores, por ejemplo

John Doe, Barack Obama,...

¿Cómo puedo escribir este contenido en un archivo, por ejemplo authors.txt? El comando

\immediate\write\myfile{\printauthors}

no funciona. ¿Estoy haciendo algo mal o debería utilizar otra forma?

Respuesta1

Si \printauthorses la macro que sugerí enSobre ordenar una cadena con múltiples entradas, entonces es fácil agregar la funcionalidad. Con esta versión,

\printauthors

simplemente imprimirá los nombres mientras

\printauthors[filename.ext]

generará los mismos datos en el archivo especificado:

\documentclass{article}

\usepackage{xparse,l3sort,pdftexcmds}

\ExplSyntaxOn

% a macro from pdftexcmds that works with all engines
\cs_set_eq:Nc \konewka_strcmp:nn { pdf@strcmp }

\NewDocumentCommand{\addauthor}{ o m m }
 {
  \IfNoValueTF{#1}
   {
    \konewka_add_author:nnn { #3 } { #2 } { #3 }
   }
   {
    \konewka_add_author:nnn { #1 } { #2 } { #3 }
   }
 }

\NewDocumentCommand{\printauthors}{ o }
 {
  \IfNoValueTF { #1 }
   {
    \konewka_print_authors:
   }
   {
    \konewka_print_authors_to_file:n { #1 }
   }
 }

\seq_new:N \g_konewka_authors_id_seq
\seq_new:N \l__konewka_authors_full_seq
\iow_new:N \g_konewka_write_authors_stream 

\msg_new:nnn { konewka/authors } { author~exists }
 {
  The ~ author ~ #1 ~ already ~ exists; ~ it ~ won't ~ be ~ added ~ again
 }

\cs_new_protected:Npn \konewka_add_author:nnn #1 #2 #3
 {
  \prop_if_exist:cTF { g_konewka_author_#1_prop }
   {
    \msg_warning:nnn { konewka/authors } { author~exists } { #1 }
   }
   {
    \seq_gput_right:Nn \g_konewka_authors_id_seq { #1 }
    \prop_new:c { g_konewka_author_#1_prop }
    \prop_gput:cnn { g_konewka_author_#1_prop } { fname } { #2 }
    \prop_gput:cnn { g_konewka_author_#1_prop } { lname } { #3 }
   }
 }

\cs_new_protected:Npn \konewka_print_authors:
 {
  \__konewka_sort_authors:
  \seq_use:Nn \l__konewka_authors_full_seq { ,~ }
 }

\cs_new_protected:Npn \konewka_print_authors_to_file:n #1
 {
  \iow_open:Nn \g_konewka_write_authors_stream { #1 }
  \__konewka_sort_authors:
  \iow_now:Nx \g_konewka_write_authors_stream
   {
    \seq_use:Nn \l__konewka_authors_full_seq { ,~ }
   }
  \iow_close:N \g_konewka_write_authors_stream
 }

\cs_new_protected:Npn \__konewka_sort_authors:
 {
  \seq_gsort:Nn \g_konewka_authors_id_seq
   {
    \string_compare:nnnTF {##1} {>} {##2} {\sort_reversed:} {\sort_ordered:}
   }
  \seq_clear:N \l__konewka_authors_full_seq
  \seq_map_inline:Nn \g_konewka_authors_id_seq
   {
    \seq_put_right:Nx \l__konewka_authors_full_seq
     {
      \prop_item:cn { g_konewka_author_##1_prop } { fname }
      \c_space_tl
      \prop_item:cn { g_konewka_author_##1_prop } { lname }
     }
   }
 }

\prg_new_conditional:Npnn \string_compare:nnn #1 #2 #3 {TF}
  {
   \if_int_compare:w \konewka_strcmp:nn {#1}{#3} #2 \c_zero
    \prg_return_true:
   \else:
    \prg_return_false:
   \fi
  }

\ExplSyntaxOff

\begin{document}

\addauthor{John}{Doe}
\addauthor{Harry}{Potter}
\addauthor[Uthor]{Archibald}{\"Uthor}
\addauthor{John}{Doe}
\addauthor{Bill}{Clinton}
\addauthor{Barack}{Obama}

\printauthors

\printauthors[\jobname.txt]

\end{document}

El contenido de \jobname.txtes

Bill Clinton, John Doe, Barack Obama, Harry Potter, Archibald \"Uthor

Tenga en cuenta que solía \jobnameno dañar ninguno de mis archivos.

Respuesta2

Si estás usando \printauthorsesto:Sobre ordenar una cadena con múltiples entradasentonces esta macro no es expandible, por lo que no se puede usar en \immediate\write. Tienes que dividir el procesamiento en dos pasos: preparar y usar. El paso de "preparación" realiza la clasificación y esta macro no se puede ampliar. El paso "usar" sólo amplía el resultado del paso de preparación.

Puedo mostrar este concepto en mi ejemplo, pero no puedes usar este código directamente porque no estás usando TeX simple.

\input opmac

\def\sort{\begingroup\setprimarysorting\def\iilist{}\sortA}
\def\sortA#1#2{\ifx\relax#1\sortB\else
  \expandafter\addto\expandafter\iilist\csname,#1\endcsname
  \expandafter\preparesorting\csname,#1\endcsname
  \expandafter\edef\csname,#1\endcsname{{\tmpb}{#2}}%
  \expandafter\sortA\fi
}
\def\sortB{\def\message##1{}\dosorting
  \def\act##1{\ifx##1\relax\else \seconddata##1\sortC \expandafter\act\fi}%
  \gdef\tmpb{}\expandafter\act\iilist\relax
  \endgroup
}
\def\sortC#1&{\global\addto\tmpb{{#1}}}

\def\sortauthors{\def\tmp{}\expandafter\sortauthorsA\authors [] {} {}; }
\def\sortauthorsA [#1] #2 #3; {%
   \ifx^#1^\expandafter\sort\tmp\relax\relax \let\sortedauthors=\tmpb
   \else\addto\tmp{{#1}{#2 #3}}\expandafter\sortauthorsA\fi
}
\def\printauthors{\expandafter\printauthorsB\sortedauthors\relax}
\def\printauthorsB#1{\ifx\relax#1\else #1, \expandafter\printauthorsB\fi}

\newwrite
\def\authors{[Doe] John Doe; [Potter] Harry Potter; [Clinton] Bill Clinton;
             [Uthor] Archibald \"Uthor; [Obama] Barack Obama; }

\sortauthors
\immediate\write\myfile{\printauthors}
\bye

Respuesta3

Si \printauthorsrealmente es solo una macro simple que se expande a una cadena, entonces esto es suficiente:

\documentclass{article}
\newwrite\myfile
\newcommand{\printauthors}{John Doe, Barack Obama}
\begin{document}
\immediate\openout\myfile=authors.txt
\immediate\write\myfile{\printauthors}
\end{document}

VerCómo escribir un comando para archivar

información relacionada