Regex 如何将字符串按4分组?

Regex 如何将字符串按4分组?,regex,perl,Regex,Perl,我有字符串1234567890,我想将其格式化为1234567890 我写这个正则表达式: $str =~ s/(.{4})/$1 /g; 但是在这种情况下,12345678这不起作用。我在结尾处有多余的空格: >>1234 5678 << 如何重写正则表达式以修复该情况?上下文是您的朋友: join(' ', $str =~ /(.{1,4})/g) 在列表上下文中,匹配将包含所有四个字符的块(以及任何比字符串末尾的短的块——多亏了贪婪)join将确保块之间用空格

我有字符串
1234567890
,我想将其格式化为
1234567890

我写这个正则表达式:

$str =~ s/(.{4})/$1 /g;
但是在这种情况下,
12345678
这不起作用。我在结尾处有多余的空格:

>>1234 5678 <<

如何重写正则表达式以修复该情况?上下文是您的朋友:

join(' ', $str =~ /(.{1,4})/g)
在列表上下文中,匹配将包含所有四个字符的块(以及任何比字符串末尾的短的块——多亏了贪婪)
join
将确保块之间用空格分隔,并且末尾没有尾随空格

如果
$str
很大,并且临时列表增加了过多的内存占用,那么您可能只需要执行
s///g
并去掉尾部空间

我倾向于在正则表达式中使用最简单的模式。另外,我还没有测量过,但是对于长字符串,仅仅一个
切块
可能比
s///g
中的条件模式便宜:

$ echo $'12345678\n123456789' | perl -lnE 's/(.{1,4})/$1 /g; chop; say ">>$_<<"'
>>1234 5678<<
>>1234 5678 9<<

$echo$'12345678\n123456789'| perl-lnE's/(.{1,4})/$1/g;印章;说“>$\up>来修复正则表达式,我应该写:

$str =~ s/(.{4}(?=.))/$1 /g;
我应该在
?=。
周围加上括号。如果没有括号,
?=。
将被视为非贪婪匹配,后跟
=。


因此,我们匹配四个字符并在它们后面加上空格。然后我向前看,仍然有字符。例如,正则表达式将不匹配字符串
1234

只需使用
解包

use strict;
use warnings 'all';

for ( qw/ 12345678 1234567890 / ) {
    printf ">>%s<<\n", join ' ', unpack '(A4)*';
}
使用严格;
使用“全部”警告;
适用于(qw/12345678 1234567890/){

printf“>>%s只需向前看,就可以看到您至少还剩下一个字符:

$ echo $'12345678\n123456789' | perl -lnE 's/.{4}\K(?=.{1})/ /g; say ">>$_<<"'
>>1234 5678<<
>>1234 5678 9<<

$echo$'12345678\n123456789'| perl-lnE的/{4}\K(?=.{1})//g;说“>>$\up>你的语法几乎正确。你需要的不是
?=.
,而是
(?=)
(paren是先行语法的一部分)。因此:

但您不需要非捕获分组:

s/(.{4}(?=.))/$1 /g
我认为如果捕获不包括前瞻性,则更清楚:

s/(.{4})(?=.)/$1 /g
根据您的示例数据,非单词边界断言也适用:

s/(.{4})\B/$1 /g
或使用\K自动保留匹配的零件:

s/.{4}\B\K/ /g

你可以写
$str=~s/{4}\K(?!$)//g;
,但你也可以把结果咀嚼一下“使问题的措辞听起来像是你犯了错误,这就是为什么建议你更新问题的原因。现在看,我意识到这是试图指出
s/((?:.{4})?=)的具体问题。”/$1/g;
…抱歉。这可能是重复的,这很有意思。谢谢我使用了lookahead来防止拖尾spacestrange,但是我自己使用
s/(.4}(?=))/$1/g
的答案被版主删除了(@EugenKonkov抱歉,我的错。它被标记为“必须是对文章的编辑”,我读了第一句话,它看起来像是对问题的更正,因此我删除了它。(习惯于看到不好的帖子,每天大约2500面旗帜,所以我的眼睛对我撒谎)。再次抱歉:(
s/(.{4})(?=.)/$1 /g
s/(.{4})\B/$1 /g
s/.{4}\B\K/ /g