2010-04-17 42 views
26

我想添加一定數量的前導零(比如說最多3)到一個字符串的所有數字。例如:使用正則表達式來添加前導零

輸入:/2009/5/song 01 of 12

輸出:/2009/0005/song 0001 of 0012

做什麼用正則表達式來做到這一點的最好方法是什麼?

編輯:

我拿起第一個正確的答案。但是,所有的答案都值得一讀。

+0

首先,您需要使用正則表達式(單詞/數字)將文本拆分爲組件,然後使用數字格式添加前導零。 – serg 2010-04-17 16:20:35

+0

謝謝serg555。爲什麼不把它作爲答案?例如, – hpique 2010-04-17 16:44:33

回答

5

使用的東西,它支持一個回調,所以你可以處理匹配:

>>> r=re.compile(r'(?:^|(?<=[^0-9]))([0-9]{1,3})(?=$|[^0-9])') 
>>> r.sub(lambda x: '%04d' % (int(x.group(1)),), 'dfbg345gf345', sys.maxint) 
'dfbg0345gf0345' 
>>> r.sub(lambda x: '%04d' % (int(x.group(1)),), '1x11x111x', sys.maxint) 
'0001x0011x0111x' 
>>> r.sub(lambda x: '%04d' % (int(x.group(1)),), 'x1x11x111x', sys.maxint) 
'x0001x0011x0111x' 
+0

感謝Ignacio。不可能不使用回調? – hpique 2010-04-17 16:49:15

+0

它可能與一個足夠複雜的正則表達式或多個正則表達式,但除非函數調用是昂貴的這種方法會更快 – 2010-04-17 16:52:45

2

樣本:

>>> re.sub("(?<!\d)0*(\d{1,3})(?!\d)","000\\1","/2009/5/song 01 of 3") 
'/2009/0005/song 0001 of 0003' 

注:

  • 它僅適用於數字1 - 9現在
  • 它沒有很好的考驗

我可以」現在不用回調就可以想到一個正則表達式*(可能有辦法做到這一點)。

這裏有兩個正則表達式來處理:

>>> x = "1/2009/5/song 01 of 3 10 100 010 120 1200 abcd" 
>>> 
>>> x = re.sub("(?<!\d)0*(\d{1,3})(?!\d)","000\\1",x) 
#'0001/2009/0005/song 0001 of 0003 00010 000100 00010 000120 1200 abcd' 
>>> 
>>> re.sub("0+(\d{4})(?!\d)","\\1",x) #strip extra leading zeroes 
'0001/2009/0005/song 0001 of 0003 0010 0100 0010 0120 1200 abcd' 
+0

不適用於011。 – kovpas 2010-04-17 16:31:22

+0

@kovpas,是的,在思考下。如果不使用回調函數有點困難,因爲填充0是可變長度。 – YOU 2010-04-17 16:34:32

+0

感謝您的迅速回復,S.Mark。更改了示例以挑戰您的解決方案。 – hpique 2010-04-17 16:42:47

1

另一種方法:

>>> x 
'/2009/5/song 01 of 12' 
>>> ''.join([i.isdigit() and i.zfill(4) or i for i in re.split("(?<!\d)(\d+)(?!\d)",x)]) 
'/2009/0005/song 0001 of 0012' 
>>> 

或者:

>>> x 
'/2009/5/song 01 of 12' 
>>> r=re.split("(?<!\d)(\d+)(?!\d)",x) 
>>> ''.join(a+b.zfill(4) for a,b in zip(r[::2],r[1::2])) 
'/2009/0005/song 0001 of 0012' 
26

在Perl:

s/([0-9]+)/sprintf('%04d',$1)/ge; 
+2

+ 1這是一個華麗簡單的正則表達式,並且符合這個法案。 – dawg 2010-04-17 18:28:07

+8

讓我想通過與我的Java實現進行比較來學習Pearl。 – hpique 2010-04-17 21:12:47

1

如果你的正則表達式實現不支持向後看和/或先行斷言,您還可以使用正則表達式:

(^|\D)\d{1,3}(\D|$) 

而更換與$1 + padLeft($2, 4, "0") + $3的匹配,其中$1是第一組的匹配,padLeft(str, length, padding)是前綴strpadding的函數,直到長度爲length爲止HED。

0

這是一個沒有回調或遞歸的Perl解決方案。它確實使用代碼執行的Perl正則表達式擴展來代替直接替換(e開關),但這很容易擴展到缺少該構造的其他語言。

#!/usr/bin/perl 

while (<DATA>) { 
    chomp; 
    print "string:\t\t\t$_\n"; 
# uncomment if you care about 0000000 case: 
# s/(^|[^\d])0+([\d])/\1\2/g; 
# print "now no leading zeros:\t$_\n";  
    s/(^|[^\d]{1,3})([\d]{1,3})($|[^\d]{1,3})/sprintf "%s%04i%s",$1,$i=$2,$3/ge; 
    print "up to 3 leading zeros:\t$_\n"; 
} 
print "\n"; 

__DATA__ 
/2009/5/song 01 of 12 
/2010/10/song 50 of 99 
/99/0/song 1 of 1000 
1 
01 
001 
0001 
/001/ 
"02" 
0000000000 

輸出:

string:    /2009/5/song 01 of 12 
up to 3 leading zeros: /2009/0005/song 0001 of 0012 
string:    /2010/10/song 50 of 99 
up to 3 leading zeros: /2010/0010/song 0050 of 0099 
string:    /99/0/song 1 of 1000 
up to 3 leading zeros: /0099/0/song 0001 of 1000 
string:    1 
up to 3 leading zeros: 0001 
string:    01 
up to 3 leading zeros: 0001 
string:    001 
up to 3 leading zeros: 0001 
string:    0001 
up to 3 leading zeros: 0001 
string:    /001/ 
up to 3 leading zeros: /0001/ 
string:    "02" 
up to 3 leading zeros: "0002" 
string:    0000000000 
up to 3 leading zeros: 0000000000 
1

<warning>這是假設的學術興趣,當然你應該使用回調做清楚,正確</warning>

我能夠濫用正則表達式要有兩個前導零(.NET風味):

s = Regex.Replace(s, @".(?=\b\d\b)|(?=\b\d{1,2}\b)", "$&0"); 

如果在字符串的開頭有一個數字,它將不起作用。這可以通過匹配數字之前的0寬度或數字之前的字符並將其替換爲0.

我沒有運氣將它擴展到三個前導零,當然不是更多。

1

c#使用:

string result = Regex.Replace(input, @"\d+", me => 
{ 
    return int.Parse(me.Value).ToString("0000"); 
}); 
0

結合在Xcode:

targetName=[NSString stringWithFormat:@"%05d",number]; 

給出00123對數123

0

一個有效的Scala程序替換的n個數字的所有組4. $$逃逸該行結束字符$,因爲我們正在使用StringContext(字符串前綴爲s)。

(f/:(1 to 3)){case (res,i) => 
    res.replaceAll(s"""(?<=[^\\d]|^)(\\d$i)(?=[^\\d]|$$)""", "0"*(4-i)+"$1") 
    }