哪些引擎可以扩展地比较字符串?

哪些引擎可以扩展地比较字符串?

pdfTeX 引擎引入了\pdfstrcmp可扩展字符串比较的原语,输入本身完全展开,例如

\edef\foo{\detokenize{foo}}
\ifnum\pdfstrcmp{\foo}{foo}=0 %
  \TRUE
\else
  \FALSE
\fi

详情纯 TeX 中的 \pdfstrcmp 或 \strcmp,这(几乎肯定)无法在 TeX90 中完全模拟。因此,该功能必须由引擎本身提供。哪些引擎提供了相当于的功能\pdfstrcmp

答案1

除了 pdfTeX 本身,e-pTeX 和 e-upTeX 也提供了\pdfstrcmp这个名称下的原语。在 XeTeX 中,同样的想法被实现为\strcmp:缺少pdf反映了这与 PDF 无关的事实。在 LuaTeX 中,可以模拟 Lua 中的结果:

\directlua{
  local write = tex.write
  function strcmp(A,B)
    if A == B then
      write("0")
    elseif A < B then
      write("-1")
   else
     write("1")
   end
  end
}
\long\def\luaescapeexpandedstring#1{%
  \luaescapestring{\detokenize\expandafter{\expanded{#1}}}%
}
\long\def\luastrcmp#1#2{%
  \directlua{%
    strcmp("\luaescapeexpandedstring{#1}","\luaescapeexpandedstring{#2}")
  }%
}

请注意,我们必须在这里讨论以下几点:

  • 正确处理#token 需要做一些扩展工作
  • 除了“明显的”“它们相等”的结果之外,还需要涵盖“一个大于另一个”的结果(例如,在比较相同位数的大整数值时很有用!)

因此,我们可以设置类似

\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname ifdefined\endcsname\relax
  \ERROR
  \expandafter\endinput
\fi
\ifdefined\directlua
  \directlua{
    local write = tex.write
    function strcmp(A,B)
      if A == B then
        write("0")
      elseif A < B then
        write("-1")
     else
       write("1")
     end
    end
  }
  \long\def\luaescapeexpandedstring#1{%
    \luaescapestring{\detokenize\expandafter{\expanded{#1}}}%
  }
  \long\def\stringcompare#1#2{%
    \directlua{%
      strcmp("\luaescapeexpandedstring{#1}","\luaescapeexpandedstring{#2}")
    }%
  }
\else
  \ifdefined\pdfstrcmp
    \long\def\stringcompare#1#2{\pdfstrcmp{#1}{#2}}
  \else
    \ifdefined\strcmp
      \long\def\stringcompare#1#2{\strcmp{#1}{#2}}
    \else
      \ERROR
    \fi
  \fi
\fi

以引擎中立的方式进行定义\stringcompare(注意,我避免使用原始名称,因为所需的扩展数与宏包装器不同)。

相关内容