2011-04-26 109 views
0

我試圖創建兩個正則表達式來向字符串中的某些值添加引號。基本上,該字符串會是這樣:正則表達式來匹配任何東西,但超過兩個空格

999   date    Doe, John E.    London   123456789 

我想圍繞名稱,以便如果此文件導出爲CSV,它不會被分開。這是我迄今爲止

$line =~ s/([^\s{2,}]*,[^\s{2,}]*)/"$1"/g; 

我覺得應該找到任何逗號和任何靠近它,直到它找到兩個或更多的空間,但它不工作。謝謝您的幫助。

+0

你不能把量詞放在這些方括號內的字符類中。他們無法將其量化爲非人。 – tchrist 2011-04-26 12:52:37

+1

@tchrist我之前使用過這個方法,但沒有使用限定括號'{}'。你可以用這個來返回xml括號後面的所有內容,例如,像這樣:'[^ <>] *)/' – atatko 2011-04-26 13:01:30

+0

方括號。 – tchrist 2011-04-26 13:02:35

回答

8

你問任何東西除了 2個或更多的空間。

我同意unpack是更自然的方式來做到這一點。但split是一種使用圖案形狀的餅乾切割器的方法。任何不是在該模式是一個返回字段。所以這個:

@fields = split /\h{2,}/, $line; 
$line = join(" " x 2 => map { "($_)" } @fields); 

可能就夠了。

+0

是的,這個工作正常!感謝您的幫助 – atatko 2011-04-26 13:19:24

+2

@atatko:很高興幫助。請注意,我使用'\ h'作爲*水平空白*。這是一個在Perl 5.10中首次出現的新捷徑。在這個版本之前,你必須使用'\ p {HorizSpace}',這個類型很長,人們通常只使用'\ s',同時也得到*垂直空白*(也就是'\ v') 。即使它對一個特定的例子沒有影響,我也喜歡'\ h',因爲它更清楚地說明了我的意思。但是,最好在程序的頂部放置'use 5.10.0;'來表明你需要該程序的最低版本號才能正常工作。 – tchrist 2011-04-26 13:26:17

1

[]包含允許的字符範圍,2-space不是字符。

可能:

$line =~ s/ (.*? .*?)/"\1" /g; 

你可能需要更明確的瞭解,以避免對'匹配的格式。

$line =~ s/ (\w+?, [\w ]+?.)/"\1" /g; 

爲了避免在更換重複的空間,環視可以用來斷言,這也可以解決在該行的開始和結束的項目問題:

$line =~ s/(?<=^| )(\w+?, [\w ]+?.)(?=$| )/"\1"/g; 

而且是小心你的原始格式 - 你確定它不只是列對齊? (在這種情況下,足夠長的名稱或日期可能不允許列之間有2+空格)。

+0

我可以說'/ \ s {2,} *// g'將2個或更多的空格轉換爲一個空格,是否有指定任何**的方法,但** 2個或更多空格 – atatko 2011-04-26 12:41:56

+0

我想你' regex會爲[last],[first] [m]工作,但當名字是Dr. name name,name PHD Sr.時,它也需要工作。它確實需要繼續查找所有內容,字符。 – atatko 2011-04-26 12:57:06

2

如果這是一個固定寬度的數據(我的猜測是這樣),最好使用解壓縮(或普通的舊substr等等)而不是正則表達式。

+0

這可能是因爲我這個不好的例子。它不是固定的寬度,也不是數據也不是固定的。否則我會同意。 – atatko 2011-04-26 12:52:32

+0

即使不是,也許'split/{2,} /'比一個全能的正則表達式更好。 (固定寬度的數據往往不是,就像前面的字段數字太多一樣)。 – LHMathies 2011-04-26 12:55:22

1

試試這個:

s/.* \K(.*),(.*?) /"$1,$2"/

從邏輯上講,這意味着:查找兩個空格和逗號,其中兩個空間的最右端,然後是逗號和兩個空間之間的子串之間的串,子字符儘可能短。

你的方法也可以工作,如果你有正確的消極lookaheads的語法。

1

您提供的示例文本似乎被製表符或空格分隔(列對齊?)。知道哪個或正則表達式不起作用很重要。知道該模式在整個文件中是否一致也很重要。

如果按列對齊,最簡單也可能最安全的方法是簡單地對字符進行計數。例如。:

s/(^.{20})(\S*) /$1"$2"/; 

(你將不得不調整自己的20號我只是近似。)

注意,我在名字字段的一個魯莽的方式結束斬去兩個空格。這是爲了不把以下值的格式搞亂。但是如果字段填滿了邊緣,最後可能沒有兩個空格,並且正則表達式將會丟失。但是,另一方面,您無論如何都無法適應報價。

在處理這些類型的文件時,我不認爲使用泛型搜索是安全的。如果你指望逗號只出現在名字中,遲早你會發現有人認爲「紐約布朗克斯」應該在城市場地,並且你的正則表達式會被搞砸。

一個稍微更加嚴格,但複雜的正則表達式將包括上述字段:

$date='\d{2}-\d{2}-\d{2}'; # this might work for dates such as 11-10-23 

s/^(\d+\s+$date\s+)(\S+) /$1"$2"/; 

同樣在這裏的事情,如果名稱字段是不是足夠大,以適應兩個引號,它不會被添加。你應該檢查你的文件,看看是否有這種情況。如果是這樣,你需要以某種方式處理它。

我有時會發現,將某些字段的正則表達式放入單獨的變量中會有助於提高可讀性,例如上面的$ date。

祝你好運!

+0

你的「紐約布朗克斯」的例子正是爲什麼這需要更動態地工作。我的第一個例子可能過於簡單,任何一個字段都可以包含一個逗號,而當它們執行時,它應該被引號包圍。 – atatko 2011-04-26 13:10:59

相關問題