从 utf8 输入生成 ascii 字符串

从 utf8 输入生成 ascii 字符串

我想定义一个命令,它接受一个名称并从中创建一个可读的字符串,该字符串可以用作文件名。例如

John Doe-> doe-john

但是,我想避免使用特殊字符,即用非 ASCII 字符替换其 ASCII 等效字符。也就是说,我需要一个宏来删除重音符号并替换一些特殊字母,例如

æüßéñ-> aeuessen

有没有办法在 LaTeX 中以合理的努力做到这一点?

答案1

如果您使用的是inputenc(而不是 XeLaTeX/LuaLaTeX),您可以利用将inputenc扩展字符转换为重音命令这一事实。例如,ü扩展为\IeC{\"u}。因此,您可以暂时重新定义重音命令以将其删除。

例子:

\documentclass{article}
\usepackage[utf8]{inputenc}

\makeatletter
\newcommand{\stripaccents}[2]{%
 \begingroup
  % strip accents:
  \let\add@accent\@secondoftwo
  % provide replacement strings:
  \def\AE{AE}%
  \def\ae{ae}%
  \def\OE{OE}%
  \def\oe{oe}%
  \def\AA{AA}%
  \def\aa{aa}%
  \def\L{L}%
  \def\l{l}%
  \def\O{O}%
  \def\o{o}%
  \def\SS{SS}%
  \def\ss{ss}%
  \def\th{th}%
  \def\TH{TH}%
  \def\dh{dh}%
  \def\DH{DH}%
  \xdef#1{#2}%
 \endgroup
}
\makeatother

\begin{document}
\stripaccents\tmp{æüßéñ}
\show\tmp
\end{document}

由此可见:

> \tmp=macro:
->aeussen.

如果您的输入中可能出现任何其他命令,则需要添加它们,\stripaccents以便它们扩展为合理的内容。

对于变音符号,您可以暂时重新定义,\"以便它附加e到其参数:

\newcommand{\stripaccents}[2]{%
 \begingroup
  \def\"##1{##1e}% umlaut
  \let\add@accent\@secondoftwo
  \def\AE{AE}%
  \def\ae{ae}%
  \def\OE{OE}%
  \def\oe{oe}%
  \def\AA{AA}%
  \def\aa{aa}%
  \def\L{L}%
  \def\l{l}%
  \def\O{O}%
  \def\o{o}%
  \def\SS{SS}%
  \def\ss{ss}%
  \def\th{th}%
  \def\TH{TH}%
  \def\dh{dh}%
  \def\DH{DH}%
  \xdef#1{#2}%
 \endgroup
}

现在显示:

> \tmp=macro:
->aeuessen.

使用 T1 编码您还需要:

\let\@text@composite@x\@secondoftwo

在 的定义中\stripaccents,正如您在评论中提到的那样。

答案2

您必须根据给出的示例自行填充列表。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \g_schtandard_search_replace_seq

\seq_gput_right:Nn \g_schtandard_search_replace_seq { {æ}{ae} }
\seq_gput_right:Nn \g_schtandard_search_replace_seq { {ä}{ae} }
\seq_gput_right:Nn \g_schtandard_search_replace_seq { {ö}{oe} }
\seq_gput_right:Nn \g_schtandard_search_replace_seq { {ü}{ue} }
\seq_gput_right:Nn \g_schtandard_search_replace_seq { {ß}{ss} }
\seq_gput_right:Nn \g_schtandard_search_replace_seq { {ñ}{n} }
\seq_gput_right:Nn \g_schtandard_search_replace_seq { {é}{e} }

\tl_new:N \l_schtandard_input_tl

\NewDocumentCommand{\makestring}{om}
 {
  \tl_set:Nn \l_schtandard_input_tl { #2 }
  \seq_map_inline:Nn \g_schtandard_search_replace_seq
   {
    \regex_replace_all:nnN ##1 \l_schtandard_input_tl
   }
  \IfNoValueTF{#1}
   {
    \tl_use:N \l_schtandard_input_tl
   }
   {
    \tl_set_eq:NN #1 \l_schtandard_input_tl
   }
 }
\ExplSyntaxOff

\begin{document}

\makestring{æüßéñ}

\makestring[\foo]{æüßéñ}\texttt{\meaning\foo}

\end{document}

在此处输入图片描述

答案3

如果你只需要文件名,但不需要它们是“人类可读的”,那么你可以利用\pdfstringdef

\documentclass{article}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[unicode]{hyperref}

\makeatletter
\begingroup
\catcode`| 0 \catcode`\\ 12
|gdef|makestring@i\#1#2#3#4%
     {#1#2#3|if|relax#4|expandafter|@gobbletwo|fi|makestring@i#4}
|endgroup
\newcommand*{\makestring}[2]{%
   \pdfstringdef\makestring@{#2}%
   \edef#1{\expandafter\makestring@i\makestring@\relax}%
}
\makeatother



\begin{document}

\makestring{\foo}{æüßéñ}

\texttt{\meaning\foo}

\end{document}

在此处输入图片描述


此主题的一个变体效率更高,它显示 utf8 字节。如果需要,可以生成十六进制。(实际上,utf8.def这里可能可以使用宏)

\documentclass{article}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\makeatletter
\newcommand*\MakeString[2]{%
   \begingroup
    \def\UTFviii@two@octets##1##2{\the\numexpr`##1\relax\the\numexpr`##2}%
    \def\UTFviii@three@octets##1##2##3{\the\numexpr`##1\relax\the\numexpr`##2\relax\the\numexpr`##3\relax}%
    \def\UTFviii@four@octets##1##2##3##4{\the\numexpr`##1\relax\the\numexpr`##2\relax\the\numexpr`##3\relax\the\numexpr`##4\relax}%
   \xdef#1{#2}%
  \endgroup
}
\makeatother

\begin{document}

\MakeString{\foo}{æüßéñ}

\texttt{\meaning\foo}

\show\foo
\end{document}

生成:

> \foo=macro:
->195166195188195159195169195177.
l.23 \show\foo

我应该改进,以便每个字节产生一个三位数的小数,这里前导零被去掉!


好的,这里没有剥离并且每个字节有 2 个十六进制数字。

编辑删除了额外包的使用。定义的\Byte@tohex宏可能已由utf8-inputenc内部提供,未经检查。

\documentclass{article}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\makeatletter
% I have not checked but maybe utf8-inputenc provides already
% similar macro (not even using e-TeX)
\def\Byte@tohex #1%
   {\expandafter
    \Byte@tohex@\the\numexpr(`#1+8)/16-1\expandafter
    .\the\numexpr`#1.}%
\def\Byte@tohex@ #1.#2.%
   {\Byte@onehex #1.%
    \expandafter\Byte@onehex\the\numexpr #2-16*#1.%
   }
\def\Byte@onehex #1.%
   {\ifcase #1
    0\or1\or2\or3\or4\or5\or6\or7\or8\or9%
     \or A\or B\or C\or D\or E\or F%
   \fi
   }%
\newcommand*\MakeString[2]{%
   \begingroup
    \def\UTFviii@two@octets##1##2{\Byte@tohex{##1}\Byte@tohex{##2}}%
    \def\UTFviii@three@octets##1##2##3{\Byte@tohex{##1}\Byte@tohex{##2}\Byte@tohex{##3}}%
    \def\UTFviii@four@octets##1##2##3##4{\Byte@tohex{##1}\Byte@tohex{##2}\Byte@tohex{##3}\Byte@tohex{##4}}%
   \xdef#1{#2}%
  \endgroup
}
\makeatother
\begin{document}

\MakeString{\foo}{æüßéñ}

\texttt{\meaning\foo}

\show\foo
\end{document}

在日志中产生

> \foo=macro:
->C3A6C3BCC39FC3A9C3B1.
l.27 \show\foo

相关内容