使用sed将替换限制为匹配空间?

时间:2011-03-06 18:51:15

标签: sed

有没有办法只使用sed在匹配空间内替换?

即。给出以下一行,是否有办法只替换“。”匹配单引号中包含的字符并保护“。”没有用单引号括起来的字符?

输入:

'ECJ-4YF1H10.6Z' ! 'CAP' ! '10.0uF' ! 'TOL' ; MGCDC1008.S1 MGCDC1009.A2

期望的结果:

'ECJ-4YF1H10-6Z' ! 'CAP' ! '10_0uF' ! 'TOL' ; MGCDC1008.S1 MGCDC1009.A2

或者这只是perl或awk可能更适合的工作吗?

感谢您的帮助,

标记

3 个答案:

答案 0 :(得分:0)

$ cat phoo1234567_sedFix.sed
#! /bin/sed -f
/'[0-9][0-9]\.[0-9][a-zA-Z][a-zA-Z]'/s/'\([0-9][0-9]\)\.\([0-9][a-zA-Z][a-zA-Z]\)'/\1_\2/

这回答了您的具体问题。如果您需要修复的模式并不总是与您提供的示例相同,那么您需要修改此行的多个副本,并修改reg-expressions以匹配新的更改目标。

请注意,cmd分为2部分,“/'[0-9] [0-9]。[0-9] [ - zA-Z] [azA-Z]'/”说,必须匹配具有此模式的行,而尾随“s /'([0-9] [0-9])。([0-9] [a-zA-Z] [a-zA-Z])'/ \ 1_ \ 2 /“,是进行替换的部分。您可以在最后的'/'之后添加'g',以便在每一行中对此模式的所有实例进行替换。

匹配模式中的\(\)对转换为命令替换侧的编号缓冲区(即\ 1 \ 2)。这就是awk没有的sed能力。

如果你要做很多这样的工作,我强烈推荐O'Rielly的Sed And Awk书。通过sed如何工作所花费的时间将被多次偿还。

我希望这会有所帮助。

P.S。因为您似乎是新用户,如果您得到的答案可以帮助您,请记住将其标记为已接受,或者给它一个+(或 - )作为有用的答案。

答案 1 :(得分:0)

尝试使用分而治之的技巧:

sed "s/\('[^']*'\)/\n&\n/g;s/\(\n'[^.]*\)\.\([^']*Z'\)/\1-\2/g;s/\(\n'[^.]*\)\.\([^']*uF'\)/\1_\2/g;s/\n//g" inputfile

说明:

  • s/\('[^']*'\)/\n&\n/g - 在每对单引号及其内容之前和之后添加换行符
  • s/\(\n'[^.]*\)\.\([^']*Z'\)/\1-\2/g - 使用换行符和单引号键,用短划线替换以“Z”结尾的字符串
  • s/\(\n'[^.]*\)\.\([^']*uF'\)/\1_\2/g - 使用换行符和单引号键入,用短划线替换点以“uF”结尾的字符串
  • s/\n//g - 删除第一步中添加的换行符

您可以将命令限制为仅对某些行执行操作:

sed "/foo/{s/\('[^']*'\)/\n&\n/g;s/\(\n'[^.]*\)\.\([^']*Z'\)/\1-\2/g;s/\(\n'[^.]*\)\.\([^']*uF'\)/\1_\2/g;s/\n//g}" inputfile

你可以用一些正则表达式代替“foo”。

sed的某些版本喜欢用勺子喂(而不是在命令之间使用分号,使用-e):

sed -e "/foo/{s/\('[^']*'\)/\n&\n/g" -e "s/\(\n'[^.]*\)\.\([^']*Z'\)/\1-\2/g" -e "s/\(\n'[^.]*\)\.\([^']*uF'\)/\1_\2/g" -e "s/\n//g}" inputfile

答案 2 :(得分:0)

这是一个最适合awk或任何支持分解/分割字符串的语言的工作。 IMO,使用sed执行此任务,这是基于正则表达式,虽然可行,但难以阅读和调试,因此不是最适合该工作的工具。对狂热分子没有冒犯。

awk '{
  for(i=1;i<=NF;i++)  {
     if ($i ~ /\047/ ){
        gsub(".","_",$i)
     }
  } 
}1' file

上面说的每个字段(字段分隔符默认为空格),检查是否有单引号,如果有,则替换“。”至 ”_”。这种方法很简单,不需要复杂的正则表达式。