Como escrever o resultado da macro no arquivo

Como escrever o resultado da macro no arquivo

Tenho uma macro \printauthors que contém uma lista de autores, por exemplo

John Doe, Barack Obama,...

Como posso escrever esse conteúdo em um arquivo, por exemplo authors.txt. O comando

\immediate\write\myfile{\printauthors}

não funciona. Estou fazendo algo errado ou devo usar outra maneira?

Responder1

Se \printauthorsfor a macro que sugeri emAo classificar uma string com múltiplas entradas, será fácil adicionar a funcionalidade. Com esta versão,

\printauthors

irá apenas imprimir os nomes enquanto

\printauthors[filename.ext]

produzirá os mesmos dados no arquivo 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}

O conteúdo de \jobname.txté

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

Observe que eu costumava \jobnamenão destruir nenhum dos meus arquivos.

Responder2

Se você estiver usando \printauthorsisso:Ao classificar uma string com múltiplas entradasentão esta macro não é expansível, portanto não pode ser usada em arquivos \immediate\write. Você tem que dividir o processamento em duas etapas: preparação e uso. A etapa de "preparação" classifica e esta macro não é expansível. A etapa "usar" apenas expande o resultado da etapa de preparação.

Posso mostrar esse conceito no meu exemplo, mas você não pode usar esse código diretamente porque não está usando TeX simples.

\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

Responder3

Se \printauthorsrealmente for apenas uma macro simples que se expande para uma string, isso é suficiente:

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

VerComo escrever um comando para arquivo

informação relacionada