web-dev-qa-db-ja.com

正規表現を使用して先行ゼロを追加する

文字列のすべての数値に特定の数の先行ゼロ(たとえば、最大3つ)を追加したいと思います。例えば:

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

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

正規表現でこれを行う最良の方法は何ですか?

編集:

最初の正解を選びました。ただし、すべての回答は一読の価値があります。

27
hpique

コールバックをサポートするものを使用して、一致を処理できるようにします。

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

Perlの場合:

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

サンプル:

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

注意:

  • 現時点では、1〜9の番号でのみ機能します
  • まだ十分にテストされていません

私は今のところコールバックを使わずに単一の正規表現を考えることはできません*(それを行う方法があるかもしれません)。

これを処理する2つの正規表現を次に示します。

>>> 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'
2
YOU

c#の使用:

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

正規表現の実装が後読みおよび/または先読みアサーションをサポートしていない場合は、次の正規表現を使用することもできます。

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

そして、一致を$1 + padLeft($2, 4, "0") + $3に置き換えます。ここで、_$1_は最初のグループの一致であり、padLeft(str, length, padding)strの前にpaddinglengthの長さになるまでプレフィックスする関数です。

1
Gumbo

<warning>これは学術的関心を前提としています。もちろん、コールバックを使用して明確かつ正確に行う必要があります</warning>

正規表現を乱用してtwo先行ゼロ(.NETフレーバー)にすることができます。

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

文字列の先頭に数字がある場合は機能しません。これは、数字の前の0幅または数字の前の文字を照合し、それらを0に置き換えることで機能します。

私はそれを3つの先行ゼロに拡張する運がありませんでした。

1
Kobi

別のアプローチ:

>>> 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'
1
YOU

有効なScalaプログラムはn桁のすべてのグループを4に置き換えます。$$StringContext を使用しているため、行末文字$をエスケープします。 =(sで始まる文字列)。

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

これがコールバックや再帰のないPerlソリューションです。単純な置換(eスイッチ)の代わりに、コード実行のPerl正規表現拡張を使用しますが、これは、その構成を欠く他の言語に非常に簡単に拡張できます。

#!/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
0
dawg

Xcodeで結合:

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

番号123に00123を与える

0
Vincent