我需要传递\jobname
给某个外部 shell 命令并使用语法读回其输入\input{|"<shell command>"}
。但是\jobname
可能包含空格。那么如何为 shell 引用它?
% pdflatex --shell-escape "file with spaces"
\documentclass[]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\begin{document}
\input{|"wc \jobname"} % how to quote \jobname here?
\end{document}
答案1
通常\jobname
设置为主输入文件名;但是,当文件中有空格时,pdftex
会在 中添加(双)引号\jobname
。
因此,为了开展业务,您必须删除这些引号。以下是\unquotedjobname
在序言中定义新宏的一种方法:
\documentclass{article}
\def\uqji#1#2\relax{%
\ifx"#1%
\uqjii#2%
\else
\let\unquotedjobname\jobname
\fi}
\def\uqjii#1"{\def\unquotedjobname{#1}}
\expandafter\uqji\jobname\relax
\begin{document}
\input{"|wc '\unquotedjobname.tex'"}
\end{document}
请注意,您必须提供.tex
扩展名,否则引用会错误。
以下是此问题的一个可能的完整解决方案;请注意,XeTeX 还接受"
名称中包含的文件名,在这种情况下,它会\jobname
用单引号括起来。在这种情况下,您可能无法使用文件名,除非您进行其他翻筋斗,所以这个问题并不那么重要。
\documentclass{article}
\usepackage{ifxetex,ifluatex}
\ifxetex
\usepackage{fontspec}
\else
\ifluatex
\usepackage{fontspec}
\else
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\fi
\fi
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\fixjobname}{sO{\xjobname}}
{
\IfBooleanTF{#1}
{ \fixjobname_print:N #2 }
{ \fixjobname_string:N #2 }
}
\tl_new:N \l_fixjobname_temp_tl
\cs_new_protected:Npn \fixjobname_print:N #1
{
\fixjobname_unquote:
\tl_set_rescan:NnV #1 { } \l_fixjobname_temp_tl
}
\cs_new_protected:Npn \fixjobname_string:N #1
{
\fixjobname_unquote:
\tl_set_eq:NN #1 \l_fixjobname_temp_tl
}
%%% Uncomment this if you don't want to use l3regex
%\cs_new_protected:Npn \fixjobname_unquote:
% {
% \tl_set_eq:NN \l_fixjobname_temp_tl \c_sys_jobname_str
% \str_case_e:nnF { \tl_head:N \l_fixjobname_temp_tl }
% {
% { " } { \fixjobname_trim: } % double quoted jobname
% { ' } { \fixjobname_trim: } % single quoted jobname (XeTeX)
% }
% { } % do nothing
% }
%\cs_new:Npn \fixjobname_trim:
% {
% \tl_set:Nx \l_fixjobname_temp_tl { \tl_tail:N \l_fixjobname_temp_tl }
% \tl_set:Nx \l_fixjobname_temp_tl { \tl_reverse:V \l_fixjobname_temp_tl }
% \tl_set:Nx \l_fixjobname_temp_tl { \tl_tail:N \l_fixjobname_temp_tl }
% \tl_set:Nx \l_fixjobname_temp_tl { \tl_reverse:V \l_fixjobname_temp_tl }
% }
%%% This works with l3regex
\cs_new_protected:Npn \fixjobname_unquote:
{
\tl_set_eq:NN \l_fixjobname_temp_tl \c_sys_jobname_str
\regex_replace_all:nnN { \A ("|') ( .* ) ("|') \Z } { \2 } \l_fixjobname_temp_tl
}
%%% End of l3regex dependent part
\cs_generate_variant:Nn \tl_set_rescan:Nnn { NnV }
\ExplSyntaxOff
\begin{document}
\fixjobname \xjobname \ (string)
\fixjobname*[\foo] \foo \ (UTF8)
\end{document}
宏\fixjobname
定义\xjobname
为一个字符串,它应该可以将其传递给 shell(但是,根据所使用的文件系统,通信可能不太好)。你可以说
\fixjobname*
通过重新扫描字符串来定义\xjobname
,这对于打印很有用。如果使用 XeLaTeX 或 LuaLaTeX,则没有区别。您仍然可以添加一个可选参数,这将是定义为保存结果的序列,而不是\xjobname
。
有两个版本:最有效的一个使用l3regex
;如果你不想处于边缘,只需取消注释前面的部分并注释掉请求l3regex
和相应的代码。
答案2
引用取决于 shell,但这是 cygwin bash:
% pdflatex --shell-escape "file with spaces"
\documentclass[]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\def\requote"#1"{'#1.tex'}
\typeout{Xwc \expandafter\requote\jobname X}
\begin{document}
\input{|"wc \expandafter\requote\jobname"} % how to quote \jobname here?
\end{document}
以上需要空格,因此\jobname
被引用。如果您还需要处理不带空格的文件名,则需要先检查是否有空格,"
然后再将其替换为'
% pdflatex --shell-escape "file with spaces"
\documentclass[]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\def\requote#1{\ifx"#1\expandafter\xrequote\else\expandafter\yrequote\fi#1}
\def\xrequote"#1"\relax{'#1.tex'}
\def\yrequote#1\relax{#1.tex}
\begin{document}
\input{|"wc \expandafter\requote\jobname\relax"} % how to quote \jobname here?
\end{document}