我想将一个字符串拆分为 n 个字符。我知道如何逐个进行拆分:
\documentclass{article}
\makeatletter
\def\s@plit<#1#2>{%
\ifx\empty#2%
#1%
\else
#1,\s@plit<#2>%
\fi}
\def\Split#1#2{\s@plit<#2\empty>}
\makeatother
\begin{document}
\Split{1}{123456789}
\end{document}
它给出:1,2,3,4,5,6,7,8,9
但我还想要 1,23,45,67,89 或 123,456,789......具体取决于第一个参数。
编辑
正向和反向工作,甚至与 相同foreach
。
\documentclass{article}
\usepackage{tikz,xparse,xstring}
\DeclareDocumentCommand{\split}{smmo}{%
\xdef\Entree{#3}%
\let\Sortie\empty%
\IfBooleanTF #1
{% sans étoile
\loop
\StrRight{\Entree}{#2}[\tmp]%
\edef\Sortie{\Sortie,\tmp}%
\StrGobbleRight{\Entree}{#2}[\Entree]%
\unless\ifx\Entree\empty
\repeat
\StrGobbleLeft{\Sortie}{1}[\Sortie]%
}
{% avec étoile dans l'ordre inverse
\loop
\StrRight{\Entree}{#2}[\tmp]%
\edef\Sortie{\tmp,\Sortie}%
\StrGobbleRight{\Entree}{#2}[\Entree]%
\unless\ifx\Entree\empty
\repeat
\StrGobbleRight{\Sortie}{1}[\Sortie]%
}
\IfNoValueTF{#4}{\Sortie}{\edef#4{\Sortie}}
}
\begin{document}
\split{2}{6513782}
\split*{2}{6513782}
\split*{2}{6513782}[\bob]
\foreach \x in \bob {[\x] }
\end{document}
答案1
更新答案
我们可以反转数字串并一次添加一位数字,在请求的项目数后插入逗号(或任何您喜欢的数字);然后我们反转回去。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\Split}{O{,} m m o }
{
\tarass_split:nnn { #1 } { #2 } { #3 }
\IfNoValueTF { #4 } { \tl_use:N } { \tl_set_eq:NN #4 } \l_tarass_string_tl
}
\tl_new:N \l_tarass_string_tl
\seq_new:N \l__tarass_string_seq
\cs_new_protected:Npn \tarass_split:nnn #1 #2 #3
{% #1 = separator, #2 = number of digits, #3 = string of digits
% clear the output token list
\tl_clear:N \l_tarass_string_tl
% first split into digits
\seq_set_split:Nnn \l__tarass_string_seq { } { #3 }
% we need to start from the end, so we reverse the sequence
\seq_reverse:N \l__tarass_string_seq
% add a comma after any group of #2 tokens, but not at the end
\seq_map_indexed_inline:Nn \l__tarass_string_seq
{
% add the digit
\tl_put_right:Nn \l_tarass_string_tl { ##2 }
% maybe add a separator
\bool_lazy_and:nnT
{% we've done #2 digits
\int_compare_p:n { \int_mod:nn { ##1 } { #2 } == 0 }
}
{% but we're not at the end
! \int_compare_p:n { ##1 == \seq_count:N \l__tarass_string_seq }
}
{% add also the separator
\tl_put_right:Nn \l_tarass_string_tl { #1 }
}
}
% reverse the string
\tl_reverse:N \l_tarass_string_tl
}
\ExplSyntaxOff
\newcommand{\ordinarycomma}{\mathord{,}}
\begin{document}
\Split{1}{123456789}
\Split{2}{123456789}
$\Split{3}{123456789}$ (not good)
$\Split[\ordinarycomma]{3}{123456789}$ (good)
$\Split[{{,}}]{3}{123456789}$ (good)
\Split{3}{123456789}[\temp]
\temp
\end{document}
可选参数是所需的分隔符,默认为逗号。如果您计划在数学模式下打印数字字符串,\ordinarycomma
则提供。也可以用作[{{,}}]
可选参数,但容易出错。
原始答案
这是正则表达式的工作:
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\Split}{ m m o }
{
\tarass_split:nn { #1 } { #2 }
\IfNoValueTF { #3 } { \tl_use:N } { \tl_set_eq:NN #3 } \l_tarass_string_tl
}
\tl_new:N \l_tarass_string_tl
\cs_new_protected:Npn \tarass_split:nn #1 #2
{
\tl_set:Nn \l_tarass_string_tl { #2 }
% we need to start from the end, so we reverse the string
\tl_reverse:N \l_tarass_string_tl
% add a comma after any group of #1 tokens
\regex_replace_all:nnN { (.{#1}) } { \1\, } \l_tarass_string_tl
% if the length of the string is a multiple of #1 a trailing comma is added
% so we remove it
\regex_replace_once:nnN { \,\Z } { } \l_tarass_string_tl
% reverse back
\tl_reverse:N \l_tarass_string_tl
}
\ExplSyntaxOff
\begin{document}
\Split{1}{123456789}
\Split{2}{123456789}
\Split{3}{123456789}[\temp]
\temp
\end{document}
尾随的可选参数是xstring
样式:如果指定了,则结果将放入该控制序列中。
答案2
\StrSplit
包中的宏可能xstring
会有帮助:
\documentclass{article}
\usepackage{xstring}
\def\split#1#2{%
\StrSplit{#2}{#1}\tempa\tempb
\tempa\let\tempa\empty
\unless\ifx\tempb\empty\def\tempa{,\split{#1}\tempb}\fi
\tempa
}
\begin{document}
\split{1}{1234567890}
编辑:此代码从最后一个字符拆分到第一个字符
\documentclass{article}
\usepackage{xstring}
\def\split#1#2{%
\def\splitstring{#2}\let\splitresult\empty
\loop
\StrLen\splitstring[\tempa]%
\StrSplit\splitstring{\number\numexpr\tempa-#1}\splitstring\tempb
\edef\splitresult{\unless\ifx\splitstring\empty,\fi\tempb\splitresult}%
\unless\ifx\splitstring\empty
\repeat
\splitresult
}
\begin{document}
\split{1}{1234567890}
\split{2}{1234567890}
\split{3}{1234567890}
\split{4}{1234567890}
\end{document}
答案3
这是一个基于 LuaLaTeX 的解决方案。它定义了一个名为的 Lua 函数strcomma
,该函数使用 Lua 的内置函数string.len
和string.sub
以及一个while .. do .. end
循环。
LaTeX 宏\Split
被设置为调用 的“包装器” strcomma
。请注意,\Split
可在文本和数学模式下使用——请注意,如果 TeX 处于数学模式,则逗号将被视为 math-ord 类型,而不是 math-punct 类型。
% !TEX TS-program = lualatex
\documentclass{article}
\directlua{function strcomma ( n , s )
t = ""
while string.len ( s ) > n do
t = "{,}" .. string.sub ( s, -n ) .. t
s = string.sub ( s , 1, -n-1 )
end
t = s .. t
tex.sprint ( t )
end}
\newcommand\Split[2]{\directlua{strcomma(#1,"#2")}}
\begin{document}
\Split{1}{1234}
$\Split{3}{1234567890}$
\end{document}