\filename@parse? 的 Unicode 兼容版本

\filename@parse? 的 Unicode 兼容版本

LaTeX 包含一个内部宏\filename@parse,可将文件名分解为路径和基本名称。但是,将其与 结合应用于包含 unicode 字符的文件名则pdflatex不起作用。

$ pdflatex test
...
> \filename@base=macro:
->\LGR\textalpha \LGR\texttau \LGR\textalpha .
l.6 \show\filename@base

其中test.tex包含

\documentclass{article}
\usepackage[greek]{babel}
\begin{document}
\makeatletter
\filename@parse{ατα.tex}
\show\filename@base
\makeatother
\end{document}

\LGR\textalpha \LGR\texttau \LGR\textalpha显然不是一个正确的文件名。

使用xelatexlualatex代替 可以pdflatex工作,但需要单独设置希腊字体。另一方面,\input{ατα.tex}在 下也可以工作pdflatex

\filename@parse没有不扩展 Unicode 字符的等效方法?(显然babel将它们定义为宏。)

答案1

您可以使用\file_parse_full_name:nNNN(可扩展版本\file_parse_full_name:n,用于内核中当前文件名解析的实现,例如在 中使用\input)。您可以定义一个包装器\file_parse_full_name:nNNN,以便它的工作方式与 完全相同\filename@parse

\documentclass{article}
\usepackage[greek]{babel}
\ExplSyntaxOn \makeatletter
\cs_new_protected:Npn \safe@filename@parse #1
  {
    \file_parse_full_name:nNNN {#1}
      \filename@area \filename@base \filename@ext
  }
\ExplSyntaxOff
\begin{document}
\makeatletter
\filename@parse{ατα.tex}
\show\filename@base
\safe@filename@parse{ατα.tex}
\show\filename@base
\makeatother
\end{document}

终端显示:

> \filename@base=macro:
->\LGR\textalpha \LGR\texttau \LGR\textalpha .
l.15 \show\filename@base

?
> \filename@base=macro:
->ατα.
l.17 \show\filename@base

?

另一个选择是使用将\set@curr@file{<filename>}文件名规范化为 catcode 12 个标记,然后您可以安全地\filename@parse\@curr@file提取所需的部分:

\documentclass{article}
\usepackage[greek]{babel}
\begin{document}
\makeatletter
\set@curr@file{ατα.tex}
\filename@parse\@curr@file
\show\filename@base
\makeatother
\end{document}

请注意,如果该文件名有任何设置,这种方法也将遵循文件替换。

答案2

我会简单地对文件名进行去标记

\expandafter\filename@parse\expandafter{\detokenize{ατα.tex}}

答案3

正则表达式版本仅供练习。当然最好使用\file_parse_full_name

\documentclass{article}
\usepackage[greek]{babel}
\begin{document}
\ExplSyntaxOn
% list (sequence) variable and string (token list) variable
\seq_new:N \l_path_seq
\tl_new:N \l_base_name
% split on / and store in list
\regex_split:nnNTF { / } { /home/user/ατα.ch.tex } \l_path_seq { } { }
% store last token from list in \l_base_name
\seq_pop_right:NN \l_path_seq \l_base_name
% remove .ext
\regex_replace_once:nnN { \.\w+\Z } { } \l_base_name
\show\l_base_name
\ExplSyntaxOff
\end{document}

结果:

> \l_base_name=macro:
->ατα.ch.
l.14 \show\l_base_name

答案4

我建议从 .tex-input 中抓取文件名作为逐字参数(-type in xparser) 并应用\detokenize

  • 当抓取-type-arguments 您可以使用不平衡花括号和多个连续空格的文件名。
  • -type 确保没有哈希值/没有类别 6(参数)的明确字符标记并且没有控制序列标记被标记。 (\detokenize将双重哈希值并在控制字标记后面附加空格,并且对控制序列标记进行反标记的结果取决于 的当前值\escapechar。)
  • \detokenize依次将活跃角色变成第 12 类和第 10 类角色。
  • 类别代码 10 的字符不属于控制符号的名称无论它们在 TeX 引擎的内部字符中的代码点编号是多少表示方案总是被标记为第 10 类显式字符标记,并且字符代码 32必须牢记。
\makeatletter
\NewDocumentCommand\PassTofilename@parse{+v}{%
  \expandafter\filename@parse\expandafter{\detokenize{#1}}%
}
\PassTofilename@parse"\relax#}  {ατα.tex"
\show\filename@base
\stop

utf8-shell 上的控制台输出:

$ pdflatex test.tex
This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(./test.tex
LaTeX2e <2020-10-01> patch level 4
L3 programming layer <2021-02-18>
> \filename@base=macro:
->\relax#}  {ατα.
l.6 \show\filename@base
                       
? 
 )
No pages of output.
Transcript written on test.log.

相关内容