如何将字符串分组为4?

时间:2017-04-14 17:13:49

标签: regex perl

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

我写这个正则表达式:

$str =~ s/(.{4})/$1 /g;

但是对于这种情况12345678,这不起作用。我最后得到了多余的空白:

>>1234 5678 <<

我尝试用lookahead重写正则表达式:

s/((?:.{4})?=.)/$1 /g;

如何重写正则表达式来修复这种情况?

5 个答案:

答案 0 :(得分:8)

只需使用 public class Main extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation); navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); } private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { FragmentManager fm = getFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); kalkulatorFragment kalkulator_fragment = new kalkulatorFragment(); wzoryFragment wzory_fragment = new wzoryFragment(); definicjeFragment definicje_fragment = new definicjeFragment(); switch (item.getItemId()) { case R.id.kalkulator: ft.replace(android.R.id.content, kalkulator_fragment); ft.commit(); return true; case R.id.wzory: ft.replace(android.R.id.content, wzory_fragment); ft.commit(); return true; case R.id.definicje: ft.replace(android.R.id.content, definicje_fragment); ft.commit(); return true; } return false; } <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:design="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/linear" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/definicjeFragment" android:name="com.thegodofcoding.adamgreloch.ultracalcalpha.definicjeFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" tools:layout="@layout/definicje_view" /> <fragment android:id="@+id/wzoryFragment" android:name="com.thegodofcoding.adamgreloch.ultracalcalpha.wzoryFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" tools:layout="@layout/wzory_view" /> <fragment android:id="@+id/kalkulatorFragment" android:name="com.thegodofcoding.adamgreloch.ultracalcalpha.kalkulatorFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" tools:layout="@layout/kalkulator_view" /> </FrameLayout> <android.support.design.widget.BottomNavigationView android:id="@+id/navigation" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="@color/bottomNavBar" android:layout_alignParentBottom="true" design:menu="@menu/bottom_nav_items" />

即可
unpack

输出

use strict;
use warnings 'all';

for ( qw/ 12345678 1234567890 / ) {
    printf ">>%s<<\n", join ' ', unpack '(A4)*';
}

答案 1 :(得分:6)

上下文是你的朋友:

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<<

答案 2 :(得分:4)

你的语法几乎是正确的。而不仅仅是?=.,您需要(?=.)(parens是超前语法的一部分)。所以:

s/((?:.{4})(?=.))/$1 /g

但是你不需要非捕获分组:

s/(.{4}(?=.))/$1 /g

而且我认为捕获并不包括前瞻更清楚:

s/(.{4})(?=.)/$1 /g

根据您的示例数据,非字边界断言也有效:

s/(.{4})\B/$1 /g

或使用\ K自动保留匹配的部分:

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

答案 3 :(得分:3)

要修复正则表达式,我应该写:

$str =~ s/(.{4}(?=.))/$1 /g;

我应该在?=.附近添加括号。没有它们?=.被计为非贪婪匹配,后跟=.

所以我们匹配四个字符并在它们之后追加空格。然后我展望未来还有角色。例如,正则表达式与字符串1234

不匹配

答案 4 :(得分:1)

只需使用预览即可确定至少剩下一个字符:

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