我有字符串1234567890
,我想将其格式化为1234 5678 90
我写这个正则表达式:
$str =~ s/(.{4})/$1 /g;
但是对于这种情况12345678
,这不起作用。我最后得到了多余的空白:
>>1234 5678 <<
我尝试用lookahead重写正则表达式:
s/((?:.{4})?=.)/$1 /g;
如何重写正则表达式来修复这种情况?
答案 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<<