인수의 첫 글자를 위 첨자로 인쇄하고 마지막 두 글자를 아래 첨자로 인쇄하는 명령을 정의하고 싶습니다. 따라서 다음을 입력하면:
\mynewcommand{abcde}
그것은 같은 일을해야
\textsuperscript{a}bc\textsubscript{de}
이러한 명령을 사용하면 몇 시간의 시간을 절약할 수 있지만 어떻게 해야 할지 모르겠습니다.
편집: 죄송합니다. 명확하지 않았을 것 같습니다. 중간 부분이 모든 것이 될 수 있습니다. 따라서 첫 글자만 위 첨자로, 마지막 두 글자는 아래 첨자로 써야 합니다.
나에게 필요한 것은:
\anothernewcommand{a some text that can contain \textit{other commands} cd}
다음과 동일하게 수행해야 하는 것
\textsuperscript{a} some text that can contain \textit{other commands} \textsubscript{cd}
답변1
나는 다음과 같은 구문이 더 명확할 것이라고 믿습니다 \mynewcommand{a}{bc}{de}
. 어쨌든 위 첨자 뒤와 아래 첨자 앞의 공백 처리가 다른 두 가지 구현을 제공할 수 있습니다. 골라보세요.
\documentclass{article}
%\usepackage{xparse} % not needed for LaTeX 2020-10-01
\ExplSyntaxOn
\NewDocumentCommand{\mynewcommandA}{m}
{
\textsuperscript{\tl_range:nnn { #1 } { 1 } { 1 } }
\tl_range:nnn { #1 } { 2 } { -3 }
\textsubscript{\tl_range:nnn { #1 } { -2 } { -1 } }
}
\NewDocumentCommand{\mynewcommandB}{m}
{
\tl_set:Nn \l_tmpa_tl { #1 }
\tl_replace_all:Nnn \l_tmpa_tl { ~ } { \c_space_tl }
\textsuperscript{\tl_range:Nnn \l_tmpa_tl { 1 } { 1 } }
\tl_range:Nnn \l_tmpa_tl { 2 } { -3 }
\textsubscript{\tl_range:Nnn \l_tmpa_tl { -2 } { -1 } }
}
\ExplSyntaxOff
\begin{document}
\textbf{Leading and trailing spaces are not kept}
\mynewcommandA{abcde}
\mynewcommandA{a some text that can contain \textit{other commands} cd}
\bigskip
\textbf{Leading and trailing spaces are kept}
\mynewcommandB{abcde}
\mynewcommandB{a some text that can contain \textit{other commands} cd}
\end{document}
추가 정보. 이 함수는 \tl_range:nnn
세 개의 인수를 사용합니다. 첫 번째 인수는 텍스트이고, 두 번째와 세 번째 인수는 추출할 범위를 지정하는 정수입니다. 그래서 {1}{1}
첫 번째 항목을 추출합니다(일 수도 있지만 \tl_head:n
균일성을 위해 더 복잡한 함수를 사용했습니다). 반면 {-2}{-1}
마지막 두 항목을 지정합니다(음수 인덱스를 사용하여 추출이 끝에서 시작됩니다). {2}{-3}
두 번째 항목부터 오른쪽부터 세 번째 항목까지의 범위를 지정합니다.
그러나 추출된 부분의 경계에 있는 공백을 유지하기 위해서는 먼저 공백을 로 대체해야 하며 \c_space_tl
, 이는 공백으로 확장되지만 추출 기능에 의해 잘리지는 않습니다. 구문은 \tl_set:Nnn
동일하며 첫 번째 인수만 tl 변수여야 합니다.
답변2
복잡성을 위해 TeX 기본 수준에서 이 문제를 해결하는 방법을 보여줍니다.
\newcount\bufflen
\def\splitbuff #1#2{% #1: number of tokens from end, #2 data
% result: \buff, \restbuff
\edef\buff{\detokenize{#2} }%
\edef\buff{\expandafter}\expandafter\protectspaces \buff \\
\bufflen=0 \expandafter\setbufflen\buff\end
\advance\bufflen by-#1\relax
\ifnum\bufflen<0 \errmessage{#1>buffer length}\fi
\ifnum\bufflen>0 \edef\buff{\expandafter}\expandafter\splitbuffA \buff\end
\else \let\restbuff=\buff \def\buff{}\fi
\edef\tmp{\gdef\noexpand\buff{\buff}\gdef\noexpand\restbuff{\restbuff}}%
{\endlinechar=-1 \scantokens\expandafter{\tmp}}%
}
\def\protectspaces #1 #2 {\addto\buff{#1}%
\ifx\\#2\else \addto\buff{{ }}\afterfi \protectspaces #2 \fi}
\def\afterfi #1\fi{\fi#1}
\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\setbufflen #1{%
\ifx\end#1\else \advance\bufflen by1 \expandafter\setbufflen\fi}
\def\splitbuffA #1{\addto\buff{#1}\advance\bufflen by-1
\ifnum\bufflen>0 \expandafter\splitbuffA
\else \expandafter\splitbuffB \fi
}
\def\splitbuffB #1\end{\def\restbuff{#1}}
% --------------- \mynewcommand implementation:
\def\textup#1{$^{\rm #1}$} \def\textdown#1{$_{\rm #1}$}
\def\mynewcommand#1{\mynewcommandA#1\end}
\def\mynewcommandA#1#2\end{%
\textup{#1}\splitbuff 2{#2}\buff \textdown{\restbuff}}
% --------------- test:
\mynewcommand{abcde}
\mynewcommand{a some text that can contain {\it other commands} cd}
\bye
답변3
다양성을 위해 LuaLaTeX 기반 솔루션이 있습니다. 이는 Lua의 문자열 함수를 활용 string.sub
하고 string.len
해당 작업을 수행하는 Lua 함수를 설정합니다. 또한 \mynewcommand
Lua 함수에 전달하기 전에 인수를 한 번 확장하는 LaTeX "래퍼" 매크로를 설정합니다 .
솔루션은 실제로 Lua 문자열 함수의 변형을 사용 하며 unicode.utf8.sub
,unicode.utf8.len
\mynewcommand
utf8로 인코딩된 문자의 유효한 문자열이 되도록 허용합니다. (물론 그러기 위해서는인쇄문자열의 문자에 적합한 글꼴을 로드해야 합니다.) 인수에는 \mynewcommand
기본 형식과 매크로가 포함될 수 있습니다.
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode} % for "\luaexec" and "\luastringO" macros
\luaexec{
% Define a Lua function called "mycommand"
function mycommand ( s )
local s1,s2,s3
s1 = unicode.utf8.sub ( s, 1, 1 )
s2 = unicode.utf8.sub ( s, 2, unicode.utf8.len(s)-2 )
s3 = unicode.utf8.sub ( s, -2 )
return ( "\\textsuperscript{" ..s1.. "}" ..s2.. "\\textsubscript{" ..s3.. "}" )
end
}
% Create a wrapper macro for the Lua function
\newcommand\mynewcommand[1]{\directlua{tex.sprint(mycommand(\luastringO{#1}))}}
\begin{document}
abcde $\to$ \mynewcommand{abcde}
öçäßüéà $\to$ \mynewcommand{öçäßüéà}
\mynewcommand{a some text that can contain \textit{\textbf{other commands}} cd}
\end{document}