含内嵌引号的CSV字符串分割问题:Java正则表达式失效求助
Hey there! Dealing with tricky CSV data that has embedded or escaped quotes can be such a headache—especially when your go-to regex split suddenly stops working. Let's break down what's going wrong and fix it.
Your initial regex ,(?=([^\"]*\"[^\"]*\")*[^\"]*$) works for basic quoted CSV fields because it relies on matching commas that sit outside paired double quotes. But when you have a field like "33,"44,55", the unescaped single quote inside breaks the pairing logic. The regex can't distinguish between a quote that's part of the field content and one that closes the field, so it splits incorrectly.
Regex is great for many tasks, but CSV parsing has edge cases (escaped quotes, newlines in fields, etc.) that make regex unreliable. Here are two solid approaches:
1. Use a Dedicated CSV Library (Recommended)
Libraries like Apache Commons CSV handle all CSV edge cases out of the box. They're built specifically for this kind of problem!
Step 1: Add the Dependency
If you're using Maven, add this to your pom.xml:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-csv</artifactId> <version>1.10.0</version> </dependency>
Step 2: Parse Your CSV
This code will correctly handle fields with embedded quotes and commas:
import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; import java.io.StringReader; import java.io.IOException; public class CsvHandler { public static void main(String[] args) throws IOException { // Your input string (note: standard CSV uses "" to escape a single ") String input = "111,222,\"33,\"\"44,55\"\",666,\"77,88\",\"99\""; // Configure CSV format to recognize " as the quote character and "" as escaped " CSVFormat csvFormat = CSVFormat.DEFAULT .withQuote('"') .withEscape('"'); // Parse and iterate through records/fields try (CSVParser parser = CSVParser.parse(new StringReader(input), csvFormat)) { for (CSVRecord record : parser) { for (String field : record) { System.out.println(field); } } } } }
Output:
111 222 33,"44,55 666 77,88 99
2. Manual Parsing with Regex (If You Can't Use Libraries)
If you need to avoid third-party libraries, use a regex that matches entire CSV fields instead of splitting on commas. This handles embedded quotes and commas properly:
import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ManualCsvParser { public static void main(String[] args) { String input = "111,222,\"33,\"44,55\",666,\"77,88\",\"99\""; List<String> fields = new ArrayList<>(); // Regex to match: quoted fields (with possible escaped "") or unquoted fields Pattern fieldPattern = Pattern.compile("\"([^\"]*(?:\"\"[^\"]*)*)\"|([^,]+)"); Matcher matcher = fieldPattern.matcher(input); while (matcher.find()) { String field; if (matcher.group(1) != null) { // For quoted fields, replace "" with " to fix escaped quotes field = matcher.group(1).replace("\"\"", "\""); } else { // Unquoted field, take as-is field = matcher.group(2); } fields.add(field); } // Print the result fields.forEach(System.out::println); } }
Regex works for simple CSV, but once you hit edge cases like embedded quotes, dedicated CSV libraries are way more reliable. They handle all the weird nuances of the CSV spec so you don't have to!
内容的提问来源于stack exchange,提问作者Shalaj

