我想从文本文件中读取几行,用“样式”包装\texttt
每行,然后将其连接到我可以在文档中使用的宏。我想出了这个 MWE:
\documentclass{article}
\usepackage{filecontents} % tlmgr install filecontents
\begin{filecontents*}{test-2.txt}
some more
words in
here so as
to eventually
print
\end{filecontents*}
\usepackage{xstring}
\def\totcontent{}
\def\mystyle#1{\texttt{#1}}
% related: http://tex.stackexchange.com/questions/116078/expand-command-read-from-file
\newread\myread
\makeatletter
\immediate\openin\myread=test-2.txt
\@whilesw\unless\ifeof\myread\fi{%
\readline\myread t\expandafter o\csname tmpline\endcsname %
\typeout{Got tmpline: \tmpline} %
\StrGobbleRight{\tmpline}{1}[\tmpline] % remove the ^^M newline (last 1 char)
\ifx\tmpline\empty\else %
%\edef\totcontent{\totcontent, \tmpline} % works without mystyle
%\edef\totcontent{\totcontent, \mystyle{\tmpline}} % fail, breaks
% via http://tex.stackexchange.com/a/74709/2595:
\g@addto@macro\totcontent{, \mystyle{\tmpline}} % compiles, but no content in output
\fi %
}
\immediate\closein\myread
\makeatother
\begin{document}
\typeout{totcontent is: \totcontent.}
I got this: \totcontent.
\end{document}
在所有情况下,我都会得到以下文件读数:
Got tmpline: some more^^M
Got tmpline: words in^^M
Got tmpline: here so as^^M
Got tmpline: to eventually^^M
Got tmpline: print^^M
Got tmpline: ^^M
xstring
...这意味着行结尾被保留,所以我用's删除“字符串”末尾的字符\StrGobbleRight
。
第一种情况,\edef\totcontent{\totcontent, \tmpline}
工作正常,但没有样式——然后输入内容显示:
totcontent is: , some more, words in, here so as, to eventually, print.
第二种情况,,\edef\totcontent{\totcontent, \mystyle{\tmpline}}
完全失效:
! Argument of \@xs@StrGobbleRight has an extra }.
<inserted text>
\par
l.30 }
在这里我打算将\mystyle
其用作占位符宏 - 期望它在连接中\edef
会向下扩展为\texttt
标记,我记得这些标记是\protect
ed,因此不会进一步扩展。显然,这没有奏效。
第三种情况,\g@addto@macro\totcontent{, \mystyle{\tmpline}}
实际上可以编译,但是给出的结果为:
totcontent is: , \texttt {}, \texttt {}, \texttt {}, \texttt {}, \texttt {}.
...这很接近,但仍然不是我想要的(我希望\texttt
由循环中的相应参数填充)。
那么,我该如何进行连接呢?最后我得到的结果如下:
totcontent is: , \texttt {some more}, \texttt {words in}, \texttt {here so as}, \texttt {to eventually}, \texttt {print}.
...这样它的排版也会如我们期望的那样吗?
As per comments, example with `\read`:
\documentclass{article}
\usepackage{filecontents} % tlmgr install filecontents
\begin{filecontents*}{test-2.txt}
some more
words in
here so as
to eventually
print
\end{filecontents*}
\def\totcontent{}
\def\mystyle#1{\texttt{#1}}
\newread\myread
\makeatletter
\immediate\openin\myread=test-2.txt
\@whilesw\unless\ifeof\myread\fi{%
\read\myread to \tmpline %
\typeout{Got tmpline: \tmpline} %
% \ifx\tmpline\empty\else %
\ifx\tmpline\par\else %
%\edef\totcontent{\totcontent, \tmpline} % works without mystyle
%\edef\totcontent{\totcontent, \mystyle{\tmpline}} % fail, breaks
\g@addto@macro\totcontent{, \mystyle{\tmpline}} % compiles, but no content in output
\fi %
}
\immediate\closein\myread
\makeatother
\begin{document}
\typeout{totcontent is: \totcontent.}
I got this: \totcontent.
\end{document}
印刷:
Got tmpline: some more
Got tmpline: words in
Got tmpline: here so as
Got tmpline: to eventually
Got tmpline: print
Got tmpline: \par
然后\edef\totcontent{\totcontent, \mystyle{\tmpline}}
失败了:
! Use of \@pr@videpackage doesn't match its definition.
并\g@addto@macro\totcontent{, \mystyle{\tmpline}}
产生:
totcontent is: , \texttt {\par }, \texttt {\par }, \texttt {\par }, \texttt {\par }, \texttt {\par }, \texttt {\par }.
...这仍然不是我想要的...
答案1
常见的问题是行尾。您不想要\readline
,但正常\read
。
\begin{filecontents*}{\jobname.txt}
some more
words in
here so as
to eventually
print
\end{filecontents*}
\documentclass{article}
\makeatletter
\newread\myread
\makeatletter
\def\strip@final@space{\expandafter\strip@final@sp@ce\@tempa\strip@final@sp@ce}
\def\strip@final@sp@ce#1 \strip@final@sp@ce{\def\@tempa{#1}}
\def\a@par{\par}
\toks@={}
\openin\myread=\jobname.txt
\@whilesw\unless\ifeof\myread\fi{%
\read\myread to \@tempa
\typeout{Got tmpline: \@tempa}%
\ifx\@tempa\a@par
\else
\strip@final@space
\toks@=\expandafter{\the\expandafter\toks@\expandafter\texttt\expandafter{\@tempa}, }%
\fi
}
\edef\totcontent{\the\toks@}
\closein\myread
\makeatother
\begin{document}
\typeout{totcontent is: \totcontent.}
I got this: \totcontent.
\end{document}
这是日志文件中的输出
totcontent is: \texttt {some more}, \texttt {words in}, \texttt {here so as}, \
texttt {to eventually}, \texttt {print}, .
请注意\@tempa
永远不会为空;空行或最后一个空行将使\@tempa
扩展为\par
。
一种更简单的方法expl3
:
\begin{filecontents*}{\jobname.txt}
some more
words in
here so as
to eventually
print
\end{filecontents*}
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\seq_new:N \l_sdaau_lines_seq
\tl_new:N \l_sdaau_totcontent_tl
\ior_new:N \sdaau_read_stream
\ior_open:Nn \sdaau_read_stream { \c_job_name_tl.txt }
\ior_map_inline:Nn \sdaau_read_stream
{
%\msg_term:n {Got~line:~|#1|} % uncomment for debugging
\seq_put_right:Nn \l_sdaau_lines_seq { \texttt { #1 } }
}
\tl_set:Nx \l_sdaau_totcontent_tl { \seq_use:Nn \l_sdaau_lines_seq { ,~ } }
\tl_set_eq:NN \totcontent \l_sdaau_totcontent_tl
\ExplSyntaxOff
\begin{document}
\typeout{totcontent is: \totcontent.}
I got this: \totcontent.
\end{document}
输出为
totcontent is: \texttt {somemore}, \texttt {wordsin}, \texttt {heresoas}, \text
tt {toeventually}, \texttt {print}.
请注意,没有尾随逗号。
如果您计划在文件中留空行,则将行
\seq_put_right:Nn \l_sdaau_lines_seq { \texttt { #1 } }
进入
\tl_if_blank:nF { #1 }
{
\seq_put_right:Nn \l_sdaau_lines_seq { \texttt { #1 } }
}
答案2
您可以\addto
通过以下方式使用宏:
\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\addtolist#1{\global\addto\totcontent{, \texttt{#1}}}
\newread\infile
\openin\infile=test-2.txt
\bgroup
\endlinechar=-1 \gdef\totcontent{}%
\loop
\unless\ifeof\infile
\read\infile to\tmp
\ifx\tmp\empty \else \expandafter\addtolist\expandafter{\tmp}\fi
\repeat
\egroup
\message{totcontent is: \meaning\totcontent}
终端打印:
totcontent is: macro:->, \texttt {some more}, \texttt {words in}, \texttt {here
so as}, \texttt {to eventually}, \texttt {print}
答案3
好的,我至少得到了一个可行的版本 - 虽然我不能说我明白发生了什么;所以更博学的答案仍然会受到欢迎。但经过一番折腾之后,我得到了一个“两步”方法,通过调用来\protected@edef
工作。这是 MWE:
\documentclass{article}
\usepackage{filecontents} % tlmgr install filecontents
\begin{filecontents*}{test-2.txt}
some more
words in
here so as
to eventually
print
\end{filecontents*}
\def\totcontent{}
\def\mystyle#1{\texttt{#1}}
\def\tst{\texttt{something here}, \texttt{and else}}
\newread\myread
\makeatletter
\immediate\openin\myread=test-2.txt
\@whilesw\unless\ifeof\myread\fi{%
\read\myread to \tmpline %
\typeout{Got tmpline: \tmpline} %
%\ifx\tmpline\par % does NOT work if \tmpline is \par!
\if\tmpline\par % does work if \tmpline is \par!
\typeout{PAR} %
\else %
%\edef\mytmp{\par} \typeout{1: -\mytmp-} % dbg
%\edef\mytmp{\tmpline} \typeout{2: -\mytmp-} % dbg
\protected@edef\mytmp{\mystyle{\tmpline}} %
\typeout{mytmp: \mytmp} %
\protected@edef\totcontent{\totcontent, \mytmp}
\fi %
}
\immediate\closein\myread
\makeatother
\begin{document}
\typeout{totcontent is: \totcontent.}
I had this: \tst;
I got this: \totcontent.
\end{document}
这会在终端打印输出中产生:
Got tmpline: some more
mytmp: \texttt {some more }
Got tmpline: words in
mytmp: \texttt {words in }
Got tmpline: here so as
mytmp: \texttt {here so as }
Got tmpline: to eventually
mytmp: \texttt {to eventually }
Got tmpline: print
mytmp: \texttt {print }
Got tmpline: \par
PAR
totcontent is: , \texttt {some more }, \texttt {words in }, \texttt {here so as
}, \texttt {to eventually }, \texttt {print }.
... 并且\totcontent
排版符合您的预期,具有正确的字体和所有内容;这正是我最初想要的。