我有一段文本,我想将其自动拆分成长度相等的块。类似于\num
数字的处理方式。
我需要的是我所称的定义\makeBlocks
。下面的 MWE 应该输出:aaaaa bbbbb ccccc ddddd 后跟 abc def ghi
\documentclass{article}
\newcommand{\makeBlocks}[1]{???}
\begin{document}
\makeBlocks{5}{aaaaabbbbbcccccddddd}
followed by
\makeBlocks{3}{abcdefghi}
\end{document}
答案1
以下是一个实现l3regex
:
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand\makeBlocks{mm}
{
\geoff_makeblocks:nn { #1 } { #2 }
}
\tl_new:N \l_geoff_blocks_input_tl
\cs_new_protected:Npn \geoff_makeblocks:nn #1 #2
{
\tl_set:Nn \l_geoff_blocks_input_tl { #2 }
%\tl_reverse:N \l_geoff_blocks_input_tl
\regex_replace_all:nnN { (.{0,#1}) } { \1 \c{,} } \l_geoff_blocks_input_tl
\regex_replace_once:nnN { \c{,} \c{,} \Z } { } \l_geoff_blocks_input_tl
%\tl_reverse:N \l_geoff_blocks_input_tl
\tl_use:N \l_geoff_blocks_input_tl
}
\ExplSyntaxOff
\begin{document}
\makeBlocks{3}{abcdef}
\makeBlocks{3}{abcdefg}
\makeBlocks{3}{abcdefghi}
\makeBlocks{5}{aaaaabbbbbccccc}
\end{document}
这是从左边开始计数的。如果你想从右边开始计数,只需将标记列表反转两次,方法是取消注释这两\tl_reverse:N
行。以下是你将得到的结果:
如果希望块之间有正常的空间,只需将两\regex
行更改为
\regex_replace_all:nnN { (.{0,#1}) } { \1 \cS\ } \l_geoff_blocks_input_tl
\regex_replace_once:nnN { \cS. \cS. \Z } { } \l_geoff_blocks_input_tl
一个“全功能”宏,可以从左边或者从右边开始(带有-variant *
),并且接受分隔符作为可选参数(默认为空格)。
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand\makeBlocks{s O{~} m m }
{
\IfBooleanTF{#1}
{
\geoff_makeblocks:nnnn { #2 } { #3 } { #4 } { \__geoff_from_right: }
}
{
\geoff_makeblocks:nnnn { #2 } { #3 } { #4 } { }
}
}
\tl_new:N \l_geoff_blocks_input_tl
\tl_new:N \l_geoff_block_separator_tl
\cs_new_protected:Npn \geoff_makeblocks:nnnn #1 #2 #3 #4
{
\tl_set:Nn \l_geoff_block_separator_tl { #1 }
\tl_set:Nn \l_geoff_blocks_input_tl { #3 }
#4 % this will be nothing or \tl_reverse:N \l_geoff_blocks_input_tl
% search blocks of #2 tokens and put the separator after them
\regex_replace_all:nnN
{ (.{#2}) } % search
{ \1 \u{l_geoff_block_separator_tl} } % replace
\l_geoff_blocks_input_tl % in this list
% if the number of tokens is a multiple of #2, one too much
% separator is inserted, remove it
\regex_replace_once:nnN
{ \u{l_geoff_block_separator_tl} \Z } % search
{ } % replace
\l_geoff_blocks_input_tl % in this list
#4
\tl_use:N \l_geoff_blocks_input_tl
}
\cs_new:Npn \__geoff_from_right:
{
\tl_reverse:N \l_geoff_blocks_input_tl
}
\ExplSyntaxOff
\begin{document}
From left: \makeBlocks{3}{abcdef}
From left: \makeBlocks{3}{abcdefg}
From right: \makeBlocks*{3}{abcdefgh}
With different separator: \makeBlocks[ x ]{3}{abcdefghi}
With different number: \makeBlocks{5}{aaaaabbbbbccccc}
\end{document}
答案2
你可以使用包裹xstring
:
笔记:
- 这是解决方案的增强版本使用 \newcommand 根据模式格式化数字/字符串。
- 此代码的限制为400个字符,因此请
\foreach
根据需要调整结束值。 - 默认情况下,拆分是从左侧进行的。如果您希望从右侧进行拆分,则需要将除 之外的其他内容传入第一个可选参数
L
。 - 分隔符的定义
\Separator
非常简单,\renewcommand
您可以更改它。
代码:
\documentclass{article}
\usepackage{xstring}
\usepackage{pgf,pgffor}
\newcommand*{\StringLength}{}%
\newcommand*{\FirstOutputStringLength}{}%
\newcommand*{\TempStringA}{}%
\newcommand*{\TempStringB}{}%
\newcommand*{\Separator}{\,}%
\newcommand*{\makeBlocks}[3][L]{%
\edef\TempStringA{#3}%
\IfStrEq{#1}{L}{%
\foreach \x in {1,...,100} {%
\StrLeft{\TempStringA}{#2}%
\StrGobbleLeft{\TempStringA}{#2}[\TempStringB]%
\xdef\TempStringA{\TempStringB}%
\IfStrEq{\TempStringA}{}{\breakforeach}{\Separator}%
}%
}{%
\StrLen{\TempStringA}[\StringLength]%
\IfEq{\StringLength}{0}{}{%
\pgfmathtruncatemacro{\FirstOutputStringLength}{mod(\StringLength,#2)}%
\IfEq{\FirstOutputStringLength}{0}{%
\xdef\TempStringB{\TempStringA}%
}{%
\StrLeft{\TempStringA}{\FirstOutputStringLength}\Separator%
\StrGobbleLeft{\TempStringA}{\FirstOutputStringLength}[\TempStringB]%
}%
}%
\makeBlocks[L]{#2}{\TempStringB}%
}%
}
\begin{document}
\begin{tabular}{cll}
Num of Char & \multicolumn{1}{c}{Left} & \multicolumn{1}{c}{Right} \\
5 & \makeBlocks{5}{AB1234567890} & \makeBlocks[R]{5}{AB1234567890}\\
5 & \makeBlocks{5}{AB123456789} & \makeBlocks[R]{5}{AB123456789}\\
5 & \makeBlocks{5}{AB12345678} & \makeBlocks[R]{5}{AB12345678}\\
5 & \makeBlocks{5}{AB1234567} & \makeBlocks[R]{5}{AB1234567}\\
5 & \makeBlocks{5}{AB12} & \makeBlocks[R]{5}{AB12}\\
5 & \makeBlocks{5}{AB} & \makeBlocks[R]{5}{AB}\\
5 & \makeBlocks{5}{A} & \makeBlocks[R]{5}{A}\\ [2.0ex]
4 & \makeBlocks{4}{AB1234567890} & \makeBlocks[R]{4}{AB1234567890}\\
3 & \makeBlocks{3}{AB123456789} & \makeBlocks[R]{3}{AB123456789}\\
2 & \makeBlocks{2}{AB12345678} & \makeBlocks[R]{2}{AB12345678}\\
1 & \makeBlocks{1}{AB1234567} & \makeBlocks[R]{1}{AB1234567}\\
\end{tabular}
\bigskip
\renewcommand{\Separator}{-}%
With different separator:
\makeBlocks{4}{AB1234567890}
\makeBlocks{1}{AB1234567890}
\end{document}