2012-03-24 116 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