正規表現のプチ練習(肯定先読み、look ahead)

最近よく閲覧しているyahoo知恵袋のプログラミングカテゴリにて、以下の正規表現の質問が投稿されました。

正規表現の質問です。
1,-80000.50,-15000.50,0.40,-9999
2,-80001.50,-15002.30,0.60,123
というテキストデータで、カンマ区切りの最後の列の ,-9999 を
取り除きたい場合の置換方法がわかりません。

検索欄に^(.+)(,[0-9]+)$、 置換に$1と指示したのですが、5列目に-が含まれているとうまくいきません。
どうしたらいいでしょうか。

ベストアンサーとなった回答は以下。

検索:^([^,]*,[^,]*,[^,]*,[^,]*),.*
置換:$1

上記は至極シンプルな方法ですが、汎用的ではない。以下の正規表現が考えられます。
案1:(.*)(,.*){1}$
案2:^.*(?=,.*)

以下は案2を使ったサンプルプログラムです。

◆Pythonの場合

1import re
2text1 = "1,-80000.50,-15000.50,0.40,-9999"
3text2 = "2,-80001.50,-15002.30,0.60,123"
4regex = r'^.*(?=,.*)'
5text1 = re.search(regex, text1).group()
6text2 = re.search(regex, text2).group()
7print(text1)
8print(text2)

◆Javaの場合

 1import java.util.regex.Matcher;
 2import java.util.regex.Pattern;
 3
 4public class Main {
 5  public static void main(String[] args) {
 6    String text1 = "1,-80000.50,-15000.50,0.40,-9999";
 7    String text2 = "2,-80001.50,-15002.30,0.60,123";
 8    String regex = "^.*(?=,.*)";
 9    Pattern p = Pattern.compile(regex);
10    Matcher m1 = p.matcher(text1);
11    Matcher m2 = p.matcher(text2);
12
13    if (m1.find()){
14      System.out.println(m1.group());
15    }
16    if (m2.find()){
17      System.out.println(m2.group());
18    }
19  }
20}

上記いずれのプログラムでも出力結果は以下となる。

11,-80000.50,-15000.50,0.40
22,-80001.50,-15002.30,0.60

※awkのサンプルプログラムを載せようとしたが、上手くいかず、ネット検索したところ「awk は POSIX 拡張正規表現 (ERE) を使用するため、先読みまたは後読みをサポートしていません。」のコメントを見つけた。 https://stackoverflow.com/questions/30430502/awk-field-separator-with-regexp-lookahead-or-lookbehind

関連ページ