Comportement étrange de \ jobname

Sep 01 2020

Supposons que j'ai un fichier nommé G1 (SK).texcontenant

\def\SK{SK}

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

\expandafter\parse\jobname

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

\bye

Lorsque je l'exécute, il s'imprime distinct, même si la valeur de jobnameest "G1 (SK)". Quand j'utilise

\expandafter\parse"G1 (SK)"

il fonctionne comme prévu et imprime equal.

Comment puis-je réparer cela?

Réponses

4 egreg Sep 01 2020 at 19:56

\jobnameproduit des caractères du code de catégorie 12, tandis que le texte de remplacement de \SKcontient des caractères du code de catégorie 11.

Il existe plusieurs façons de faire face au problème. Si vous utilisez pdftexcela prend en charge les extensions e-TeX

\edef\SK{\detokenize{SK}}

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

\expandafter\parse\jobname

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

\bye

Vous pouvez également exploiter \pdfstrcmp:

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

\expandafter\parse\jobname

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

\bye

parce \pdfstrcmpque la comparaison de chaînes est indépendante des codes de catégorie (et développe les macros dans ses arguments).

Dans tous les cas, vous ne devriez pas faire \def\language, car \languagec'est une primitive TeX.

Une solution plus flexible avec 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

Cela imprime «La langue est SK», mais si j'utilise un nom de travail différent, disons XYZ(X), j'obtiens «Langue non définie ».

La commande \checklanguageest entièrement extensible et fonctionne donc dans \edef. Le jeton à exécuter pour chaque chaîne dépend de vous et de votre application prévue. Notez que vous n'avez pas besoin de vous soucier des guillemets ajoutés s'il y a un espace dans le nom, car les premières lignes extraient simplement ce qui se trouve entre le (premier ensemble de) parenthèses.

4 DonHosek Sep 01 2020 at 18:44

\jobnameattribue le code de catégorie 12 à tous les caractères sauf l'espace lorsqu'il est défini. Vous pouvez obtenir le résultat souhaité en faisant quelque chose comme ceci:

{
  \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