Странное поведение \ jobname

Sep 01 2020

Предположим, у меня есть файл с именем, G1 (SK).texсодержащий

\def\SK{SK}

\def\parse"#1 (#2)"{\def\language{#2}}

\expandafter\parse\jobname

\ifx\SK\language equal\else distinct\fi

\bye

Когда я запускаю его, он печатает distinct, даже если значение jobnameравно "G1 (SK)". Когда я использую

\expandafter\parse"G1 (SK)"

он работает как положено и печатает equal.

Как я могу это исправить?

Ответы

4 egreg Sep 01 2020 at 19:56

\jobnameпроизводит символы кода категории 12, а замещающий текст \SKсодержит символы кода категории 11.

Есть несколько способов справиться с проблемой. Если вы используете, pdftexкоторый поддерживает расширения e-TeX

\edef\SK{\detokenize{SK}}

\def\parse"#1 (#2)"{\def\filelanguage{#2}}

\expandafter\parse\jobname

\ifx\SK\filelanguage equal\else distinct\fi

\bye

Вы также можете использовать \pdfstrcmp:

\def\parse"#1 (#2)"{\def\filelanguage{#2}}

\expandafter\parse\jobname

\ifnum\pdfstrcmp{SK}{\filelanguage}=0 equal\else distinct\fi

\bye

потому \pdfstrcmpчто сравнение строк не зависит от кодов категорий (и расширяет макросы в своих аргументах).

В любом случае этого делать не следует \def\language, потому что \languageэто примитив TeX.

Более гибкое решение с expl3.

\input expl3-generic

\ExplSyntaxOn
\str_new:N \l_bak_file_language_str
\str_set_eq:NN \l_bak_file_language_str \c_sys_jobname_str
\regex_replace_once:nnN { .*? \((.*)\) .* } { \1 } \l_bak_file_language_str

% now the string variable contains the string in parentheses
% extracted from the jobname

\cs_new:Npn \checklanguage
 {
  \str_case:VnF { \l_bak_file_language_str }
   {
    {SK}{Language~is~SK}
    {AB}{Language~is~AB}
    {XYZ}{Language~is~XYZ}
   }
   {Undefined~language}
 }
\ExplSyntaxOff

\checklanguage

\bye

Это напечатает «Язык - SK», но если я использую другое имя, скажем XYZ(X), я получаю «Неопределенный язык».

Команда \checklanguageполностью расширяема и поэтому работает в \edef. Токен, выполняемый для каждой строки, зависит от вас и вашего предполагаемого приложения. Обратите внимание, что вам не нужно заботиться о добавленных кавычках, если в имени есть пробел, потому что первые строки просто извлекают то, что находится между (первым набором) круглых скобок.

4 DonHosek Sep 01 2020 at 18:44

\jobnameприсваивает код категории 12 всем символам, кроме пробела, если он установлен. Вы можете получить желаемый результат примерно так:

{
  \catcode`\S=12
  \catcode`\K=12
\gdef\sk{SK}
}
\def\parse"#1 (#2)"{\def\language{#2}}

\expandafter\parse\jobname

\ifx\sk\language equal\else distinct\fi

\bye