2012-03-24 154 views
1

我將如何替換四和五後面的逗號|但不是那些跟隨一個和兩個?正則表達式 - Sed

\"One,Two, Three\" Four, Five, Six 

sed s'/,/|/'g 

我將不勝感激一個答案,可以適用於任何逗號內的轉義引號,而不僅僅是這個例子。

另一個例子是:

Mr ,Joe,Lish,,\"Acme, Inc.\",\"9599 Park Avenue, Suite 301\",Manhattan,NY,10022,\"\"\"6 A MAILING LIST MMBR GENERAL\"\"\" 
+2

一般這種事情是不是正則表達式,因爲語言工作你要求他們明白是不是經常性的*。 – dmckee 2012-03-24 21:41:48

+0

正確。一般的正則表達式並不具有* state *關聯,這就是這裏所要求的。解析器需要保存關於它是否在引號內部的狀態信息。 – 2012-03-24 21:47:55

回答

0

有前瞻和回顧後運營商正則表達式。例如,Javascript調用

bodyText = bodyText.replace(/ Aa(?= A)/ g,'AaB');

如果後面跟着另一個「A」,則會將「Aa」替換爲「AaB」,而將「AaBA」替換爲您。它不會與「AaB」相匹配,因爲「Aa」之後沒有其他「A」。這是一個向前看的電話。

我相信lookbehind的語法是? < =。因此,如果這些操作符由您使用的軟件包支持,那麼您可以使用它們匹配「,」前面加「四」或「五」,只替換「,」。

+0

不在*我*使用的任何sed。 – dmckee 2012-03-24 22:13:04

+0

@dmckee如果你別名sed =「perl -p」',那麼它會正常工作。 :) – tchrist 2012-03-24 22:34:16

+0

@tchrist:你是​​一個生病的病人。但聰明。我的意思是用一種很好的方式。 – dmckee 2012-03-24 23:04:22

0

我想出了這樣一個:

echo '\"One,Two, Three\" Four, Five, Six' | sed 's/\(\("[^"]*"\)\?[^",]\+\),/\1 |/g' 

其中假定線就像使用sed

[ ["someting"] word, ]* ["someting"] word 
+0

這對我不起作用。我在使用終端的Mac上,如果這改變了任何東西。 – adayzdone 2012-03-24 22:14:52

1

方式一:

內容的 script.sed

## Substitute '\"' with '\n'. 
s/\\\"/\n/g 

## If there is an odd number of '\"' or the string doesn't end with '\"' I 
## will append some at the end. There is no danger, but it will be used to 
## avoid an infinite loop. 
## 1.- Save content to 'hold space'. 
## 2.- Remove all characters except '\n'. 
## 3.- Remove one of them because next command will add another one. 
## 4.- Put content in 'pattern space' to begin working with it. 
## So, if in original string there were 3 '\"', now there will be 6. ¡Fine! 
h 
s/[^\n]//g 
s/\n// 
H 
g 

## Label 'a'. 
:a 

## Save content to 'hold space'. 
h 

## Remove from first '\n' until end of line. 
s/\(\n\).*$/\1/ 

## Substitute all commas with pipes. 
s/,/|/g 

## Delete first newline. 
s/\n// 

## Append content to print as final output to 'hold space'. 
H 

## Recover rest of line from 'hold space'. 
g 

## Remove content modified just before. 
s/[^\n]*// 

## Save content to 'hold space'. 
h 

## Get first content between '\n'. 
s/\(\n[^\n]*\n\).*$/\1/ 
s/\n\{2,\}// 

## Susbtitute '\n' with original '\"'. 
s/\n/\\"/g 

## Append content to print as final output to 'hold space'. 
H 

## Recover rest of line from 'hold space'. 
g 

## Remove content printed just before. 
s/\n[^\n]*\n// 

/^\n/ { 
    s/\n//g 
    p 
    b 
} 

ba 

內容infile

\"One,Two, Three\" Four, Five, Six 
One \"Two\", Three, Four, Five 
One \"Two, Three, Four, Five\" 
One \"Two\" Three, Four \"Five, Six\" 

運行它想:

sed -nf script.sed infile 

結果如下:

\"One,Two, Three\" Four| Five| Six 
One \"Two\"| Three| Four| Five 
One \"Two, Three, Four, Five\" 
One \"Two\" Three| Four \"Five, Six\" 
+0

迴應是:undefined label'a' – adayzdone 2012-04-04 03:46:53

+0

@adayzdone:抱歉,我無法重現您的問題。我的版本是** GNU sedversión4.2.1 **,你的是什麼? – Birei 2012-04-07 17:22:30

+0

Mac 10.6.8附帶的版本 – adayzdone 2012-04-07 17:42:47

1

這可能會爲你工作:

sed 's/^/\n/;:a;s/\n\("[^"]*"\|[^,]\)/\1\n/;ta;s/\n,/|\n/;ta;s/.$//' file 

Expla國家:

  • 預先在模式空間換行。 s/^/\n/
  • 製作標籤:a
  • 將換行符移動到引號之間的字符串或不是逗號的字符之間。 s/\n\("[^"]*"\|[^,]\)/\1\n/
  • 如果替換是標籤的成功循環。 ta
  • \n,代替|\ns/\n,/|\n/
  • 如果替換是標籤的成功循環。 ta
  • 如果不進行替換,則全部刪除換行符。 s/.$//

編輯:

其實任何字符的獨特字符或組合可以用來代替\n

echo 'Mr ,Joe,Lish,,\"Acme, Inc.\",\"9599 Park Avenue, Suite 301\",Manhattan,NY,10022,\"\"\"6 A MAILING LIST MMBR GENERAL\"\"\"' | 
sed 's/^/@@@/;:a;s/@@@\("[^"]*"\|[^,]\)/\[email protected]@@/;ta;s/@@@,/|@@@/;ta;s/@@@$//' 
Mr |Joe|Lish||\"Acme, Inc.\"|\"9599 Park Avenue, Suite 301\"|Manhattan|NY|10022|\"\"\"6 A MAILING LIST MMBR GENERAL\"\"\" 
+0

我在做什麼錯了? http://i.imgur.com/NdNZ3.png – adayzdone 2012-03-25 03:10:18

+0

看起來像你的sed版本不允許換行形式爲'\ n'。如果使用bash作爲你的shell,或者通過輸入CTRL-v return來插入實際行,請嘗試用''「」$'替換所有'\ n'。另見[here](http://sed.sourceforge.net/sedfaq4.html#s4.1) – potong 2012-03-25 08:19:46

+0

查看備選編輯: – potong 2012-03-25 08:41:01