如何将字符串按 4 分组?
Posted
技术标签:
【中文标题】如何将字符串按 4 分组?【英文标题】:How to group string of characters by 4? 【发布时间】:2017-04-14 17:13:48 【问题描述】:我有字符串1234567890
,我想将其格式化为1234 5678 90
我写了这个正则表达式:
$str =~ s/(.4)/$1 /g;
但是对于这种情况12345678
这不起作用。最后我得到了多余的空格:
>>1234 5678 <<
我尝试用前瞻重写正则表达式:
s/((?:.4)?=.)/$1 /g;
如何重写正则表达式来解决这种情况?
【问题讨论】:
你可以写$str =~ s/.4\K(?!$))/ /g;
,但你也可以选择结果。
您现在已删除的答案的介绍段落,其中您说“我在写问题时注意到错误”听起来您在措辞时犯了错误,这就是原因建议您改为更新您的问题。现在看,我意识到这是试图指出 s/((?:.4)?=.)/$1 /g;
的具体问题......对不起。
Can I use unpack to split a string into characters in Perl?的可能重复
【参考方案1】:
只需使用unpack
use strict;
use warnings 'all';
for ( qw/ 12345678 1234567890 / )
printf ">>%s<<\n", join ' ', unpack '(A4)*';
输出
>>1234 5678<<
>>1234 5678 90<<
【讨论】:
【参考方案2】:上下文是你的朋友:
join(' ', $str =~ /(.1,4)/g)
在列表上下文中,匹配将匹配所有四个字符块(以及任何比字符串末尾更短的内容——多亏了贪婪)。 join
将确保块用空格分隔,并且末尾没有尾随空格。
如果$str
很大并且临时列表过多地增加了内存占用,那么您可能只想执行s///g
并去除尾随空格。
我的偏好是在正则表达式中使用最简单的模式。另外,我没有测量过,但是对于长字符串,单个chop
可能比s///g
中的条件模式便宜:
$ echo $'12345678\n123456789' | perl -lnE 's/(.1,4)/$1 /g; chop; say ">>$_<<"'
>>1234 5678<<
>>1234 5678 9<<
【讨论】:
这很有趣。谢谢 我使用前瞻来防止尾随空格【参考方案3】:您的语法几乎是正确的。您不仅需要?=.
,还需要(?=.)
(括号是前瞻语法的一部分)。所以:
s/((?:.4)(?=.))/$1 /g
但你不需要非捕获分组:
s/(.4(?=.))/$1 /g
而且我认为如果捕获不包括前瞻则更清楚:
s/(.4)(?=.)/$1 /g
根据您的示例数据,非词边界断言也有效:
s/(.4)\B/$1 /g
或者使用\K自动保留匹配的部分:
s/.4\B\K/ /g
【讨论】:
奇怪,但我自己使用s/(.4(?=.))/$1 /g
的答案已被版主删除(
@EugenKonkov 对不起,我的错。它被标记为“必须对帖子进行编辑”,我阅读了第一句话,它看起来像是对问题的更正,因此我将其删除。 (看惯了不好的帖子,每天大概2500个flag,所以我的眼睛骗了我)。再次抱歉。 :(【参考方案4】:
要修复我应该写的正则表达式:
$str =~ s/(.4(?=.))/$1 /g;
我应该在?=.
周围加上括号。没有它们?=.
被视为非贪婪匹配,然后是=.
所以我们匹配四个字符并在它们后面附加空格。然后我向前看,仍然有字符。例如,正则表达式将不匹配字符串1234
【讨论】:
【参考方案5】:只需向前看,您至少还剩一个字符:
$ echo $'12345678\n123456789' | perl -lnE 's/.4\K(?=.1)/ /g; say ">>$_<<"'
>>1234 5678<<
>>1234 5678 9<<
【讨论】:
以上是关于如何将字符串按 4 分组?的主要内容,如果未能解决你的问题,请参考以下文章