例字符串:如何構建正則表達式來解析逗號分隔值,但忽略雙引號中的逗號?
2011-03-09,4919 1281 0410 9930,55107,SAZB2314,"John, Doe" ,1-888-888-4452 ext 1813
需要標記所有的逗號而不是雙引號中的一個。
例字符串:如何構建正則表達式來解析逗號分隔值,但忽略雙引號中的逗號?
2011-03-09,4919 1281 0410 9930,55107,SAZB2314,"John, Doe" ,1-888-888-4452 ext 1813
需要標記所有的逗號而不是雙引號中的一個。
您可以使用CPAN的Text::CSV
。
如果你需要一個正則表達式,而不是像@eugene這樣的正確解析器,那麼這裏是一個嘗試。捕獲應該按順序返回列表元素。
(?:(?:([^"]*?|".*?"),)*([^"]*?|".*?"))?
或使用Text::CSV_XS,它做同樣的事情,但速度更快。
由於Text :: CSV導致文本:: CSV_XS被使用(如果可用),它不一定更快。儘管如此,我建議使用Text :: CSV_XS,因爲它消除了使用Text :: CSv的額外複雜性,並保證Text :: CSV_X通過較慢的Text :: CSV_PP獲得Text :: CSV_XS。 – ikegami 2011-03-10 21:22:24
使用Data::Record。
嘗試:
use strict;
use warnings;
use Text::ParseWords;
while (<DATA>) {
chomp;
my @f = quotewords ',', 0, $_;
for (@f) {
s/^\s*|\s*$//g;
s/^/"/ && s/$/"/ if /,/;
}
print join (",", @f), "\n";
}
__DATA__
2011-03-09,4919 1281 0410 9930,55107,SAZB2314,"John, Doe" ,1-888-888-4452 ext 1813
"ashish", "kumar", "test,1", "test2"
"foo", "b,ar", "msg1", "msg2"
我知道如何在Java中做到這一點。正則表達式在PERL中可能會有所不同,但讓我展示這個想法。有3個子句的聯合。
// 1) select any quoted text before comma
// if it fails then
// 2) select any text before comma
// if it also fails then
// 3) select any text before end of the input
final String OR = "|";
final String QUOTE = "\"[\\s]*"; //with trailing whitespaces
final String NON_QUOTES = "[^\"]*";
final String COMMA = ",";
final String NON_COMMA = "[^,]*";
final String NON_END = "[^$]+";
final String END = "$";
final Pattern p = Pattern.compile(
QUOTE+NON_QUOTES+QUOTE+COMMA+
OR+
NON_COMMA+COMMA+
OR+
NON_END+END);
它會給你比賽,不幸的是會以逗號結束,除了最後一個。沒有捕獲組,因爲用像這樣的union子句來定義它們是沒有意義的。
類似於Regexp :: Grammars,Parser :: MGC或Parse :: RecDescent將是創建等同於此的Perl代碼的方式。但對於CSV,已經有模塊可以解決這個問題。 – MkV 2012-08-20 13:37:09
我目前正在研究一個項目,這個正則表達式幫助我以完全相同的格式創建一個csv文件。
("([^"]*)",?)|(([^",]*),?)
如果一個記錄被隨機分成多行這將無法正常工作。我有這個問題,並通過確定非空匹配的計數是否正確來解決它。
請勿使用正則表達式。不要使用正則表達式。不要使用正則表達式。使用文本解析器。 – CanSpice 2011-03-10 20:01:49
但文本解析器不使用正則表達式將輸入分解爲令牌嗎? – shawnhcorey 2016-12-22 13:08:52
如果你想學習,不要使用文本解析器。 如果您想提高生產力,請不要使用正則表達式。 – 2017-11-09 00:27:29