我正在尝试修复 www.babs.gmxhome.de 中的 accessibility.sty 包的一些问题
有一个字符串比较的结果总是为假,也就是说,语言代码定义将不会被执行。
\ifthenelse{\equal{#1}{\string german}}{\gdef\LanguageCode{/Lang(DE)}}{}%
现在如果我尝试
\message{#1}
\message{\string german}
编译文档时的输出将是:
德语 德语
我真的很迷茫,为什么#1和字符串german
在这里不能与true进行比较...可能是什么原因?
答案1
该\ifthenelse
测试进行基于 token 的比较。因此,当你这样做时
\documentclass{article}
\usepackage{ifthen}
\newcommand{\foo}[1]{%
\ifthenelse{\equal{#1}{\string german}}
{TRUE}
{FALSE}%
}
\begin{document}
\foo{german}
\end{document}
发生的事情是\string
应用于第一个标记在这种情况下,它会看到一个g
。比较两个结果,它们是不一样的:一个有一个非字母然后五个字母,第二个有六个字母。这两种情况的排版方式不同:g
类别代码 12(“其他”)排版的字形与g
类别代码 11(“字母”)排版的字形相同,因此两者看起来相同。
在 TeX 中有多种方法可以进行真正的“字符串”比较。使用现代 TeX 引擎,迄今为止最简单的方法是使用\pdfstrcmp
或等效方法:
\documentclass{article}
\usepackage{pdftexcmds}
\makeatletter
\newcommand\foo[1]{%
\ifnum\pdf@strcmp{\unexpanded{#1}}{german}=0 %
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{TRUE}
{FALSE}%
}
\makeatother
\begin{document}
\foo{german}
\end{document}
这确实会进行字符串比较,忽略类别代码。如果你想坚持使用\ifthenelse
但可以假设 e-TeX,那么
\documentclass{article}
\usepackage{ifthen}
\newcommand{\foo}[1]{%
\ifthenelse{\equal{\detokenize{#1}}{\detokenize{german}}}
{TRUE}
{FALSE}%
}
\begin{document}
\foo{german}
\end{document}
将作为\detokenize
其全部的参数变成字符串。
另一种不需要任何传统 TeX 基元的方法是使用类似
\documentclass{article}
\usepackage{pdftexcmds}
\makeatletter
\newcommand\foo[1]{%
\begingroup
\def\@tempa{#1}%
\@onelevel@sanitize\@tempa
\def\@tempb{german}%
\@onelevel@sanitize\@tempb
\ifx\@tempa\@tempb
\aftergroup\@firstoftwo
\else
\aftergroup\@secondoftwo
\fi
\endgroup
{TRUE}
{FALSE}%
}
\makeatother
\begin{document}
\foo{german}
\end{document}
\@onelevel@sanitize
利用将事物转换为字符串的事实。
当然,如果你知道输入是有意义的,那么根本就没有必要使用任何去标记化
\documentclass{article}
\usepackage{ifthen}
\newcommand{\foo}[1]{%
\ifthenelse{\equal{#1}{german}}
{TRUE}
{FALSE}%
}
\begin{document}
\foo{german}
\end{document}
答案2
我想添加另一种简单的方法,在纯 TeX 中进行基于字符串的选择,而无需额外的软件包。它利用 TeX 宏扩展并用于\csname ... \endcsname
构建宏名称。
\documentclass[11pt,a4paper]{article}
\makeatletter
% define macros that are executed for every given string
\def\setlang@english{\gdef\LanguageCode{/Lang(EN)}}
\def\setlang@german{\gdef\LanguageCode{/Lang(DE)}}
\def\setlang@dutch{\gdef\LanguageCode{/Lang(NL)}}
\newcommand{\setlang}[1]{
% call the macro corresponding to argument #1
\csname setlang@#1\endcsname
}
\makeatother
% test the macro
\begin{document}
\setlang{english}
\LanguageCode
\setlang{dutch}
\LanguageCode
\end{document}
答案3
另一个选择是使用包etoolbox
(与 XeLaTeX 一起使用),这是一个 MWE
\documentclass{article}
\usepackage{etoolbox}
\begin{document}
\renewcommand{\language}{german}
\ifdefstring{\language}{german}{German}{Other}
\\
\renewcommand{\language}{english}
\ifdefstring{\language}{german}{German}{Other}
\end{document}
产生
使用的优点\ifdefstring
是,你可以将花括号留空以“执行没有什么“
\ifdefstring
{\language}{german}
{German}
{} %% do nothing