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
显然不是一个正确的文件名。
使用xelatex
或lualatex
代替 可以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.