如何将制表符输出到文件中

如何将制表符输出到文件中

使用命令\openout\write我将文本输出到文件中。如何输出制表符?

\documentclass{article}
\begin{document}
  \newwrite\tempfile
  \immediate\openout\tempfile="filename.txt"
  \immediate\write\tempfile{I want a tab at the beginning of this line}
  \immediate\closeout\tempfile
\end{document}

编辑1

按照 egreg 的解决方案,我使用\catcode`\^^I=12。如果我直接使用代码,则此方法有效,但如果我将代码括在命令中,则无效:

\documentclass{article}
\begin{document}
      \newwrite\tempfile
      \immediate\openout\tempfile="filename.txt"
      \begingroup
        \catcode`\^^I=12 %
        \immediate\write\tempfile{^^II want a tab at the beginning of this line}
      \endgroup
      \immediate\closeout\tempfile
    
    \newcommand{\test}{
    \newwrite\tempfilee
    \begingroup\catcode`\^^I=12 %
    \immediate\openout\tempfilee="filename2.txt"
        \immediate\write\tempfilee{^^II want a tab at the beginning of this line}
    \endgroup
    }
      
    \test   
    coucou
\end{document}

编辑2再次感谢 egreg。第二种解决方案有效,但如果我\test从另一个命令内部调用则无效,而这正是我需要的:

\newwrite\tempfile
\immediate\openout\tempfile=\jobname.out

\def\test{\begingroup\catcode`\^^I=12 \testaux}
\def\testaux#1{\immediate\write\tempfile{#1}\endgroup}

\newcommand{\makeit}{
\test{^^I<-TAB again}
}

\test{        <-TAB} % WORKS
\test{^^I<-TAB} %WORkS
\makeit %DOES NOT WORK
\immediate\closeout\tempfile

编辑3。egreg 的第二个解决方案有效......但如果它在内部则无效AtEndDocument

\documentclass{article}
\AtEndDocument{\test{^^Ifin du document}
\immediate\closeout\tempfile }

\begin{document}
\newwrite\tempfile
\immediate\openout\tempfile=output.txt
\catcode`\^^I=\active
\def^^I{}
\def\test#1{\begingroup
\edef^^I{\string^^I}\immediate\write\tempfile{#1}\endgroup}

\test{^^I<-coucou} %% WORKS
\def\foo{\test{^^I<-Jojo}}
\foo  %% WORKS
\end{document}

但是最后一句“fin du document”没有 TAB。

答案1

遗憾的是,在文件中写入文字 TAB 字符取决于您拥有的 TeX 发行版以及格式的初始化方式。

pdftex使用 TeX Live 发行版,pdflatex和的格式latex都已准备好,只需输入选项-translate-file=cp227.tcx,即可使 TAB 字符“可打印”。

编译输入

\newwrite\tempfile
\immediate\openout\tempfile=\jobname.out
\begingroup
  \catcode`\^^I=12 %
  \immediate\write\tempfile{^^I<-TAB}
\endgroup
\immediate\closeout\tempfile
\csname @@end\endcsname\end % trick for stopping with Plain TeX and LaTeX

使用tex和使用pdftex(在 TeX Live 发行版上)将产生两个不同的结果(我报告“十六进制转储”):

  1. 5e 5e 49 3c 2d 54 41 42 0atex

  2. 09 3c 2d 54 41 42 0apdftex

确实tex不是设置 TCX 转换,使 TAB 字符可打印。

luatex如果用或编译文件,lualatex结果将与情况 2 一样。用xetex它仍然不同。

  1. 5e 5e 49 3c 2d 54 41 42 0axetex

  2. 09 3c 2d 54 41 42 0axetex -8bit

因此,^^I以这种形式写出的是用texxetexxelatex,而以文字 TAB 的形式写出的是用pdftexpdflatex或,也可以是用和luatexlualatexxetexxelatex 假如他们被要求-8bit选择。

这个故事的寓意是:不要使用 TAB,也不要尝试将它们写入文件中,因为其结果在各个系统和机器上是不可预测的。


如何定义一个命令,将一行写入尊重 TAB 字符的文件(假设pdftex)?

必须记住,一旦 TeX 读入标记列表,类别代码就会固定。因此,必须使用不同的策略:

\newwrite\tempfile
\immediate\openout\tempfile=\jobname.out

\def\test{\begingroup\catcode`\^^I=12 \testaux}
\def\testaux#1{\immediate\write\tempfile{#1}\endgroup}

\test{        <-TAB}
\test{^^I<-TAB}

\immediate\closeout\tempfile

\csname @@end\endcsname\end

这将写入\jobname.out(再次显示十六进制转储)

09 3c 2d 54 41 42 0a 09 3c 2d 54 41 42 0a

因此写入了两个文字 TABS(第一个参数中的空格被\test认为是 TAB,不幸的是,在此系统上它可能会转换为空格)。


如果您\test还需要在另一个命令的参数中工作,那么上述技巧将不起作用:类似于 的操作\foo{x \test{^^I<-TAB}},其中接受一个参数,将会破坏在而不是 在 中\foo完成的参数的延迟抓取:当 TeX 将参数存储到它时,它会修复类别代码。\testaux\test\foo

但是还有另一个问题:TeX^^I一读取空格标记(当^^I类别代码为 10 时)就会将其规范化。所以你的问题更难解决。如果你不需要文件中的 TAB,除了为了编写它之外,你可以这样做

\catcode`\^^I=\active
\def^^I{}

\newwrite\tempfile
\immediate\openout\tempfile=\jobname.out

\def\test#1{\begingroup
  \edef^^I{\string^^I}\immediate\write\tempfile{#1}\endgroup}

\test{        <-TAB}
\test{^^I<-TAB}

\def\foo#1{#1\test{#1}}

\foo{^^I<-TAB}

\immediate\closeout\tempfile

\csname @@end\endcsname\end

这样做的局限性是 TAB 不会打印任何内容,而序列<SPACE><TAB><SPACE>将打印空格。

好好考虑一下不是沿着这条路前进。

如果需要的命令\test数量有限,可以像上面那样给出正确的定义。如果你想允许\test作为参数任何指挥部,你运气不好。


如果你需要做的只是写\AtEndDocument,你可以说

\begingroup
\catcode`\^^I=12
\gdef\EndTest{\test{^^I<-TAB}}
\endgroup
\AtEndDocument{\EndTest}

可以不定义新命令:

\begingroup
\lccode`?=`\^^I
\lowercase{\endgroup\AtEndDocument{\test{?fin du document}}}
\AtEndDocument{\immediate\closeout\tempfile}

您可以使用不同于的字符?,重要的是它是一个 12 类字符。

答案2

您可以定义一个新的宏,\mytab为 TAB 字符提供类别 12。

\begingroup
\catcode`\^^I=12
\gdef\mytab{^^I}
\endgroup

然后,使用\mytab(末尾有一个空格) 代替^^I<TAB>

\documentclass{article}
% memoize TAB char
\begingroup
\catcode`\^^I=12
\gdef\mytab{^^I}
\endgroup
% open temp file
\newwrite\tempfile
\immediate\openout\tempfile=\jobname.out
% macro to write to temp file
\def\writetotemp#1{\immediate\write\tempfile{#1}}

\AtEndDocument{\writetotemp{\mytab<-TABEND}}
\AtEndDocument{\immediate\closeout\tempfile}
\begin{document}
\immediate\write\tempfile{\mytab <-TAB1}
\writetotemp{\mytab <-TAB2}
\end{document}

以下是 的转储\jobname.out

0000000  \t   <   -   T   A   B   1  \n  \t   <   -   T   A   B   2  \n
           3c09    542d    4241    0a31    3c09    542d    4241    0a32
0000020  \t   <   -   T   A   B   E   N   D  \n
           3c09    542d    4241    4e45    0a44
0000032

相关内容