我正在尝试将几兆字节的 UTF8 文本输出为可打印格式。由于enscript
我的朋友们不喜欢 Unicode,这个 Unix SE 问题很快就转向了 LaTeX。
需求概要:将几MB的中文、拉丁文和特殊字符(即无效的LaTeX代码)处理成紧密排列的多列格式,这些格式由长行和短行组成。我知道LaTeX可以控制字体大小、间距、边距等,以及标题和页码,所以我对此不太担心。
到目前为止我遇到的问题是获取文件的可包装和支持 UTF8 的逐字输入。
有没有办法可以同时实现这两者?
例如,使用该fancyvbr
软件包,我可以很好地呈现中文文本,但没有换行:
\documentclass{article}
\usepackage{CJKutf8}
\usepackage{ucs}
\usepackage{multicol}
\usepackage{verbatim}
\usepackage[encapsulated]{CJK}
\newcommand{\myfont}{bsmi} % or {stheiti}, etc
\begin{document}
\begin{CJK}{UTF8}{\myfont}
\begin{multicols}{2}
\VerbatimInput[fontfamily=cmr]{file.txt}
\end{multicols}
\end{CJK}
\end{document}
我到目前为止还无法获得一个listings
类型环境来处理文件中的 Unicode。
我输入的内容类型的示例。这是为了格式化数千行多语言聊天日志。基本上有 100,000++ 行这样的内容:
###### 2013-10-26.223938+0000GMT.html ######
**** [email protected]/ (jabber) ****
(00:00:00) Lorem ipsum
(00:00:01) 車檢作畫病得星定局而是作的所由次園又此對這一馬的生故他試……外由懷黃客建時常嚴在位以說其配場戲回有部結一自法就生機,定的被各世皮全空!也地傳現他重城,書照展商直起眾家不思政國林年八計出地口早體故失離際們層氣,簡他廣集義,四便入的只了極。
(00:00:02) odesset ullamcorper quo. Cu adipisci assentior eam, debet definiebas eos ad. Te eos nihil populo vivendum, vix iusto noster peri
(00:00:02) odesset ullamcorper quo. Cu adip
(02:00:02) odesset ullamcorper quo. Cu adipisci assentior eam, debet d
(02:00:01) 車檢作畫病得星定局而是作的所由次園又此對這一馬的生故他試……外由懷黃客建時常嚴在位以說其配場戲回有部結一自法就生機,定的被各
(02:00:02) ok
(00:01:02) 病
(00:00:02) ok
(00:01:02)
###### 2013-10-26.223938+0000GMT.html ######
**** [email protected]/ (jabber) ****
(00:00:01) 車檢作畫病得星定局而是作展商直起眾家不思政國林年八計出地口早體故失離際們層氣,簡他廣集義,四便入的只了極。
(00:00:02) odesset ullamcorper quo. Cu adipisci assentior eam, debet definiebas eos ad. Te eos nihil populo vivendum, vix iusto noster peri
(00:00:02) odesset ullamcorper quo. Cu adip
(02:00:02) odesset ullamcorper quo.
我理想情况下正在寻找最通用的解决方案,因为输入文本不一定是明确定义的机器可读格式。
编辑还尝试使用普通包进行以下操作verbatim
:
\usepackage{verbatim}
\makeatletter
\def\@xobeysp{ }
\makeatother
文档主体中包含以下内容:
\verbatiminput{file.txt}
这适用于普通文本和中文,但无法拆分文件中出现的包含非常长的单词、URL 或长字符串的行。
答案1
正如您已经使用的,verbatim
该包很容易配置以获得正确的换行符并转义所有特殊字符。
对于 CJK 文本,xeCJK
是您的朋友。并且有一些选项可以xeCJK
控制逐字 CJK 文本的行为。
我侵入了xeCJK
软件包来调整换行符。看起来好多了,但并不完美。
% -*- coding: utf-8 -*-
% Compile with XeLaTeX
\documentclass{article}
\usepackage{etoolbox}
\usepackage{verbatim}
\makeatletter
\def\@xobeysp{\ }% Or just a space, with a different result
\let\verbatim@nolig@list\empty
\appto\verbatim@font{\raggedright}
\makeatother
\usepackage{xeCJK}% You'd better use the latest version
\setCJKmonofont{SimSun}
\xeCJKsetup{Verb=false}
\normalspacedchars{}
\ExplSyntaxOn
% Hack into xeCJK package if you want to allow linebreaks after (almost) any character.
% Delete this if you don't want that.
\tex_chardef:D \c_fifty = 50 ~
\xeCJK_inter_class_toks:nnn { Default } { Default } { \tex_penalty:D \c_one_hundred }
\xeCJK_inter_class_toks:nnn { Default } { HalfLeft } { \tex_penalty:D \c_fifty }
\xeCJK_inter_class_toks:nnn { Default } { HalfRight } { \tex_penalty:D \c_one_thousand }
\xeCJK_inter_class_toks:nnn { HalfLeft } { Default } { \tex_penalty:D \c_one_thousand }
\xeCJK_inter_class_toks:nnn { HalfLeft } { HalfLeft } { \tex_penalty:D \c_one_thousand }
\xeCJK_inter_class_toks:nnn { HalfLeft } { HalfRight } { \tex_penalty:D \c_one_thousand }
\xeCJK_inter_class_toks:nnn { HalfRight } { Default } { \tex_penalty:D \c_fifty }
\xeCJK_inter_class_toks:nnn { HalfRight } { HalfLeft } { \tex_penalty:D \c_fifty }
\xeCJK_inter_class_toks:nnn { HalfRight } { HalfRight } { \tex_penalty:D \c_one_thousand }
\ExplSyntaxOff
\begin{document}
\verbatiminput{test.log}
\end{document}
包含长行的测试日志文件:
###### 2013-10-26.223938+0000GMT.html ###### ****[电子邮件保护]/(喋喋不休)**** (00:00:00)乱数假文 (00:00:01)车检画病得星确定局其他作由次园又此对这一马的生故他试验……外由怀黄客建时常秘密在位以说明其配场戏回有部门结一自行法就生机,定的被各世皮空!也地传现他重城,书照展商直接起家不思政国林年八计出口早体故我们阶层气氛,简他广集义,四便入的只了极。 (00:00:02)odesset ullamcorper 现状。 Cu adipisci assentior eam,definiebas eos ad。人民没有生存的必要,我们有权 (00:00:02)`~!@#$%^&*()_+-={}[]|\:;"'。?/ (02:00:02)LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL长线
答案2
您可以告诉 xetex 换行中文,而不用担心通常特殊的字符。(您可能需要将更多字符设为 catcode 12,这显示了基本思想)
\documentclass{article}
\usepackage{fontspec}
\setmainfont{SimSun}
\newcommand\showlog[1]{{%
\catcode`\#=12
\catcode`\^=12
\catcode`\$=12
\obeylines
\raggedright
\XeTeXlinebreaklocale "zh"
\input{#1}}}
\begin{document}
\showlog{\jobname.txt}
\end{document}
答案3
除了 之外,您没有任何特殊字符,那么#
您可以使用简单的\input
。我的示例使用xelatex
,这使得使用 CJK 语言更加容易。
\documentclass{article}
\usepackage[margin=1cm]{geometry}
\usepackage{fontspec}
\setmainfont{Code2000}
\setmonofont{DejaVu Sans Mono}%% has no chines characters
\usepackage{pdflscape}
\newcommand\Listing[1]%
{\begin{landscape}
\catcode`\#=12%
\obeylines
% \ttfamily%%% only possible with a mono type font with chinese characters
\footnotesize
\input{#1}%
\end{landscape}}
\begin{document}
foo
\Listing{xxx.tex}%% THE EXTERNAL FILE
bar
\end{document}
答案4
我目前在这方面所做的最大努力是基于 Unix SE 上 @Gilles 的概念。它不是纯粹的 *TeX 实现,也不完美,但它让我能够将前 1.4MB 的文本压缩到 36 页:每页约 40kB 和 1400 行。
我使用 perl 预处理输入文本以转义 LaTeX 特殊字符,并在某些特殊字符(如 ?!/\$ 等)处添加软断点,以及人为地将长单词和无意义的字符串分解为带有更多软连字符的最大长度。显然,这不会考虑连字符的“好”位置,但这是一个非常小的细节,因为在几乎所有情况下,它要么在空格、特殊字符处断点,要么字符串本身没有好的断点。
然后使用 XeLaTeX 和 CJK 处理以使用 处理中文xeCJK
。它被放置在multicols
非常窄的列中,因为有很多非常短的行,我不想浪费空间。
#! /bin/bash
maxLength=12
breakableChars='\&\;\/\.\?\!\='
# break singly-occuring breakable chars, and the first one in runs with a soft hyphen
# break any un-broken runs of any ascii with a soft hyphen
# replace any backslashes with \textbackslash{}
# replace braces (except the ones in \textbackslash{})
# escape #$%&_ with backslashes
# escape ^ | and ~ with \textTHING{}
# line break after all non-empty lines
cat $1 |
perl -pe 's/(?<![\s'$breakableChars'])(['$breakableChars'])(?!\s)/\1\\-/g;' |
perl -pe 's/(((?<!-)[!-~]){'$maxLength'}(?!\s))/\1\\-/g;' |
perl -pe 's/\\(?!-)/\\textbackslash{}/g;' |
perl -pe 's/(?<!\\textbackslash){/\\{/g;' |
perl -pe 's/(?<!\\textbackslash\{)\}/\\}/g;' |
perl -pe 's/([\#\%\$\&\_])/\\\1/g;' |
perl -pe 's/\^/\\textasciicircum{}/g;'|
perl -pe 's/\|/\\textbar/g;' |
perl -pe 's/~/\\textasciitilde{}/g;' |
perl -pe 's/^(.*\S.*)$/\1\\\\/g;' > $2
cat << EOF > driver.tex
\documentclass{article}
\usepackage{fontspec}
\usepackage{multicol}
\usepackage[margin=1cm]{geometry}
\usepackage{setspace}
\usepackage{xeCJK}
\setstretch{0.5}
\setlength{\columnsep}{0.1cm}
\setmainfont{Nimbus Sans L Regular Condensed}
\setCJKmainfont{WenQuanYi Micro Hei}
\newcommand\showlog[1]{{%
\obeylines
\raggedright
\XeTeXlinebreaklocale "zh"
\input{#1}}}
\begin{document}
\raggedright
\fontsize{4}{5}\selectfont
\begin{multicols}{9}
\showlog{h.txt}
\end{multicols}
\end{document}
EOF
/opt/texbin/xelatex driver.tex
剩下的主要问题是,CJK 字体或主字体中没有的非中文、非拉丁字符不会显示。使用ucharclasses
Code2000 效果更好,但速度非常慢。