正規表現で文字列中に出現する複数の数値文字列を置換する
以下はyahoo知恵袋より正規表現の質問を抜粋したもの。思いのほか難しかったので、対応方法を備忘録として残す。
まず、質問内容は以下。
エクセルのZ列にx-1A,x-47B,xx-234D,xx-12のようなデータが複数存在します。
このデータを以下のように変更したいです。
x-001A,x-047B,xx-234D,xx-012
-の後に数字3桁に統一して他は何も変更しません。
以下のロジックで実現可能。
- 文字列をカンマ区切りで分割しリストとする
- リストから要素を1個ずつ取り出し、以下を繰り返す
2-1. 正規表現[0-9]+
により、処理中の要素から数値部分を取り出す
2-2. 数値部分をゼロ埋めして3桁にする
2-3. 処理中の要素に対し2-1で取り出した値で検索して2-2の値で置換。その結果を別途用意した置換後リストに格納 - 置換後リストをカンマ区切りで結合し、元の文字列と置き換える
◆Pythonの場合
1import re
2text = "x-1A,x-47B,xx-234D,xx-12"
3repLst = []
4regex = r'[0-9]+'
5lst = text.split(',')
6for elem in lst:
7 numStr = re.search(regex, elem).group()
8 num = int(numStr)
9 pad = f'{num:03}'
10 repLst.append(elem.replace(numStr, pad))
11print(','.join(repLst))
◆Javaの場合
1import java.util.ArrayList;
2import java.util.List;
3import java.util.regex.Matcher;
4import java.util.regex.Pattern;
5
6public class Main {
7 public static void main(String[] args) {
8 String text = "x-1A,x-47B,xx-234D,xx-12" ;
9 String regex = "[0-9]+" ;
10 Pattern p = Pattern.compile(regex);
11 Matcher m;
12 String numStr, pad;
13 int num;
14 List<String> repLst = new ArrayList<String>();
15
16 String[] lst = text.split(",");
17 for(String elem : lst){
18 m = p.matcher(elem);
19 if(m.find()){
20 numStr = m.group();
21 num = Integer.parseInt(numStr);
22 pad = String.format("%03d", num);
23 repLst.add(elem.replace(numStr, pad));
24 }
25 }
26 System.out.println(String.join(",", repLst));
27 }
28}
◆Excel VBAの場合
1Sub test()
2 Dim str, text
3 text = "x-1A,x-47B,xx-234D,xx-12"
4
5 Dim regex, m
6 Set regex = CreateObject("VBScript.RegExp")
7 regex.Pattern = "[0-9]+"
8 regex.Global = True
9
10 Dim lst, elem, repLst(), i, numStr, pad
11 lst = Split(text, ",")
12 i = 0
13 For Each elem In lst
14 Set m = regex.Execute(elem)
15 If m.Count > 0 Then
16 If i = 0 Then
17 ReDim repLst(i)
18 Else
19 ReDim Preserve repLst(i)
20 End If
21 numStr = m(0).Value
22 pad = Right("000" & numStr, 3) ' ゼロ埋め
23 repLst(i) = Replace(elem, numStr, pad)
24 i = i + 1
25 End If
26 Next
27 Debug.Print Join(repLst, ",")
28 Set regex = Nothing
29End Sub
これらのコードの実行結果は、期待どおりに x-001A,x-047B,xx-234D,xx-012 となる。