매크로 결과를 파일에 쓰는 방법

매크로 결과를 파일에 쓰는 방법

예를 들어 저자 목록이 포함된 \printauthors 매크로가 있습니다.

John Doe, Barack Obama,...

이 내용을 파일(예: authors.txt. 명령

\immediate\write\myfile{\printauthors}

작동하지 않습니다. 내가 뭔가 잘못하고 있는 걸까요, 아니면 다른 방법을 사용해야 합니까?

답변1

\printauthors내가 제안한 매크로 라면여러 항목이 포함된 문자열 정렬 시, 그러면 기능을 추가하는 것이 쉽습니다. 이 버전에서는

\printauthors

동안에는 이름만 인쇄합니다.

\printauthors[filename.ext]

지정된 파일에 동일한 데이터를 출력합니다.

\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}

의 내용 \jobname.txt

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

나는 \jobname내 파일을 훼손하지 않는 데 사용했습니다.

답변2

\printauthors이것을 사용하는 경우 :여러 항목이 포함된 문자열 정렬 시그러면 이 매크로는 확장할 수 없으므로 에서 사용할 수 없습니다 \immediate\write. 처리를 준비와 사용의 두 단계로 나누어야 합니다. "준비 중" 단계는 정렬을 수행하며 이 매크로는 확장할 수 없습니다. "사용" 단계는 준비 단계의 결과만 확장합니다.

내 예제에서 이 개념을 보여줄 수 있지만 일반 TeX를 사용하지 않기 때문에 이 코드를 직접 사용할 수 없습니다.

\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

답변3

\printauthors실제로 문자열로 확장되는 단순한 매크로라면 다음과 같이 충분합니다 .

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

보다파일에 명령을 쓰는 방법

관련 정보