将字符串解析为数字标记和非数字标记

将字符串解析为数字标记和非数字标记

我有一个字符串,想要将其解析为数字和非数字。

对于我的目的来说:

A数字任何一个是任意连续的数字串或者以 . 开头的连续数字字符串,后跟另一个连续字符串。

A非数字是任何不是数字

例如

ljksadflh23898129hfafh0324.22234

应该解析成类似

ljksadflh, 23898129, hfafh, 0324.22234

或者

ljksadflh/23898129/hfafh/0324.22234

或者任何您喜欢的东西,只要列表保持相同的顺序。

答案1

使用实验性的(但几乎可以发布)软件包l3regex(在l3experimentalCTAN 上的捆绑包中找到),这项任务很容易完成。

\documentclass{article}
\usepackage{l3regex,xparse}
\ExplSyntaxOn
\seq_new:N \l_uiy_result_seq
\NewDocumentCommand { \UiySplit } { m }
  {
    \regex_extract_all:nnN { \D+ | \d+(?:\.\d*)? } {#1} \l_uiy_result_seq
    \seq_map_inline:Nn \l_uiy_result_seq { item:~##1\par }
  }
\ExplSyntaxOff
\begin{document}
  \UiySplit{ljksadflh23898129hfafh0324.22234}
\end{document}

\regex行将用户输入拆分#1为由一个或多个(+)非数字(\D)或(|)一个或多个数字( )组成的部分\d,后面可能跟着(?作用于组(...),我们希望它是“非捕获的”,使用 完成(?:...))一个点(\.转义点,因为点具有特殊含义)和零个或多个数字(\d*)。下面的行映射了我们找到的所有匹配项,其中##1是单个匹配项。当然,您可以对序列的项目执行任何您想做的事情\l_uiy_result_seq

编辑:该模块还提供正则表达式替换。如果我没记错语法,下面的代码应该可以工作。

\ExplSyntaxOn
\seq_new:N \l_uiy_result_seq
\NewDocumentCommand { \UiySplit } { m }
  {
    \tl_set:Nn \l_uiy_result_tl {#1}
    \regex_replace_all:nnN
        { (\D+) (\d+(\.\d*)) }
        { \c{uiy_do:nn} \cB{\1\cE} \cB{\2\cE} }
        \l_uiy_result_tl
    \tl_use:N \l_uiy_result_tl
  }
\cs_new_protected:Npn \uiy_do:nn #1#2 { \use:c {#1} {#2} }
\ExplSyntaxOff

这次,我捕获了非数字序列和数字,作为捕获组\1\2。每个这样的出现都由宏替换\uiy_do:nn\c在这种情况下,转义表示“构建命令”),然后是开始组(\cB)字符{(这次\c表示类别代码),然后是非数字(\1),然后是结束组(\cE)字符},然后是另一个\cB{,数字和结束\cE}

之后,标记列表看起来像\uiy_do:nn {ljksadflh} {1}。然后我们只需将其内容与 一起使用即可\tl_use:N。最后一步是实际定义\uiy_do:nn。在这里,我将其定义为简单地从 构建一个命令#1,并为其提供参数#2。这个非常简单的操作可以在替换步骤中使用\c{\1}“从 group 的内容构建一个命令\1”来完成,从技术上讲,如果未定义相关命令,它会稍微好一些,产生“未定义的控制序列”错误。进行该错误检测的另一种选择是用 替换\use:c {#1} {#2}\cs_if_exist_use:cF {#1} { \msg_error:nnx { uiy } { undefined-command } } {#2}并带有适当定义的错误消息。

答案2

这个纯粹是通过扩展来实现的,所以写入等都是安全的:

$ tex split
This is TeX, Version 3.1415926 (Web2C 2010)
(./split.tex
ljksadflh, 23898129, hfafh, 0324.22234
6, ljksadflh, 23898129, hfafh, 0324.22234
 )
No pages of output.
Transcript written on split.log.




\def\xytest#1{?%
\ifnum`#1<46?\else
     \ifnum`#1>57?\else
     \ifnum`#1=47?\else!\fi\fi\fi}

\def\x#1{%
 \ifx\relax#1%
 \else
 \if\xytest#1%
 #1\expandafter\expandafter\expandafter\xx
 \else
 #1\expandafter\expandafter\expandafter\y
 \fi
 \fi}

\def\xx#1{%
 \ifx\relax#1%
 \else
 \if\xytest#1%
 #1\expandafter\expandafter\expandafter\xx
 \else
 , #1\expandafter\expandafter\expandafter\y
 \fi
 \fi}


\def\y#1{%
 \ifx\relax#1%
 \else
 \if\xytest#1%
 , #1\expandafter\expandafter\expandafter\xx
 \else
 #1\expandafter\expandafter\expandafter\y
 \fi
 \fi}


\immediate\write20{\x ljksadflh23898129hfafh0324.22234\relax}

\immediate\write20{\x 6ljksadflh23898129hfafh0324.22234\relax}


\bye

答案3

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% Document commands
% \NewDocumentCommand\parsestring { m } { \uiy_parse_string:n { #1 } }

\NewDocumentCommand\MyMacro { s O{0} m }
  {
   \IfBooleanTF { #1 }
     {
      \uiy_parse_string:n { #3 }
      \uiy_my_macro_parsed:n { #2 }
     }
     {
      \clist_set:Nn \l_uiy_parsed_string_clist { #3 }
      \uiy_my_macro_parsed:n { #2 }
     }
  }

% Inner commands
\tl_const:Nn \c_uiy_numbers_tl {0123456789.}
\tl_new:N \l_uiy_parsed_string_tl
\clist_new:N \l_uiy_parsed_string_clist
\seq_new:N \l_uiy_main_seq
\bool_new:N \l_uiy_previous_is_number_bool
\cs_generate_variant:Nn \tl_if_in:NnTF {NV}

\cs_new:Npn \uiy_parse_string:n #1
  {
   \tl_clear:N \l_uiy_parsed_string_tl
   \seq_set_split:Nnn \l_uiy_main_seq {} { #1 }
   \seq_pop_left:NN \l_uiy_main_seq \l_uiy_parsed_string_tl
   \tl_if_in:NVTF \c_uiy_numbers_tl \l_uiy_parsed_string_tl
     { \bool_set_true:N \l_uiy_previous_is_number_bool }
     { \bool_set_false:N \l_uiy_previous_is_number_bool }
   \seq_map_inline:Nn \l_uiy_main_seq
     {
      \tl_if_in:NnTF \c_uiy_numbers_tl { ##1 }
        {
         \bool_if:NF \l_uiy_previous_is_number_bool
           { \tl_put_right:Nn \l_uiy_parsed_string_tl { , } }
         \tl_put_right:Nn \l_uiy_parsed_string_tl { ##1 }
         \bool_set_true:N \l_uiy_previous_is_number_bool
        }
        {
         \bool_if:NT \l_uiy_previous_is_number_bool   
           { \tl_put_right:Nn \l_uiy_parsed_string_tl { , } }
         \tl_put_right:Nn \l_uiy_parsed_string_tl { ##1 } 
         \bool_set_false:N \l_uiy_previous_is_number_bool
        }
     }
   \clist_set:NV \l_uiy_parsed_string_clist \l_uiy_parsed_string_tl
  }

\cs_new:Npn \uiy_my_macro_parsed:n #1
  {
   \int_compare:nTF { #1 = 0 }
     {
      \clist_map_inline:Nn \l_uiy_parsed_string_clist
        {
         % here you do something with the successive items
         item: ~  ##1 \par
        }
     }
     {
      % here you do something with the #1-th item
      \clist_item:Nn \l_uiy_parsed_string_clist { #1 - 1 } \par
     }
  }
\ExplSyntaxOff

\begin{document}

1. \MyMacro*{ljksadflh23898129hfafh0324.22234}

\bigskip

2. \MyMacro{ljksadflh,23898129,hfafh,0324.22234}

\bigskip

\bigskip

3. \MyMacro*[2]{ljksadflh23898129hfafh0324.22234}

\bigskip

4. \MyMacro[2]{ljksadflh,23898129,hfafh,0324.22234}

\end{document}

通过这个,你可以看到一个未解析的字符串被 *-variant 调用;可选参数指示只访问列表中的一个项目。当然,如果不知道数据的预期用途,就不可能说得更多。

在此处输入图片描述

答案4

这是我自己的 latex3 版本,与 egreg 的类似。这是一个概述版本,但可以修改。在此发布仅供参考。它在某些方面更简洁一些,因为它对标记使用了一些直接解析,而不是创建标记列表然后解析标记列表。(它不使用任何序列列表,因为不需要它们)

\ExplSyntaxOn
\tl_const:Nn \tlc_Digits {0123456789.}
\tl_const:Nn \tlc_Space { }
\bool_new:N \b_EON
\bool_new:N \b_FirstDigit

\NewDocumentCommand\ParseCmd{m}
{\tl_if_blank:nTF {#1} {}{

    % Initialize Variables
    \bool_set_false:N \b_EON
    \bool_set_true:N \b_FirstDigit

    % Parse Tokens
    \tl_map_inline:nn {#1}
    {
        % Checks to see if the token is a digit or not
        \tl_if_in:NnTF \tlc_Digits {##1}
        {
            \bool_set_false:N \b_EON

            \bool_if:NTF \b_FirstDigit { [ } { , }
            ##1

            \bool_set_false:N \b_FirstDigit
        }
        {   % Token not a digit

            \bool_set_true:N \b_FirstDigit
            \tl_if_in:NnTF \tlc_Space {##1} { } { }
            \bool_if:NTF \b_EON { } { ], }
            \bool_set_true:N \b_EON
        }


    }

    % used for very last token
    \bool_if:NTF \b_EON { } { ] }

}}
\ExplSyntaxOff

相关内容