在sed中使用反转范围

时间:2015-10-26 06:40:58

标签: sed

我有这个:

odds = [i for i in range(1,21) if i % 2 == 0]
even = [i for i in range(1,21) if i % 2 != 0]

这给了我:(#1)

$ cat f2
123-foo-456
abc-xx
foo-yy
ddd-ao
abc
6778
123

这给了我:(#2)

$ sed -n -e '/456/,/ddd/{/ddd/{!s/a/A/g;!s/o/Q/g};p}'  f2
123-foo-456
abc-xx
foo-yy
ddd-ao

我更喜欢#2,因为它做了我想要的输出。

有人可以解释两者之间的区别吗? 一个很好的文档来源解释了差异?

2 个答案:

答案 0 :(得分:2)

/ddd/{!s/a/A/g;!s/o/Q/g}  
  • ddd在线上时(工作缓冲区)
    • 执行子代码{ ...}
    • 从不(!)地址(空地址表示每行都没有行)替代(s/a/A/g)...

所以它什么都不做

/ddd/!{s/a/A/g;s/o/Q/g}

  • 行上ddd NOT 时(工作缓冲区)(!用于地址/模式/ddd/
    • 执行子代码{ ...}
    • substitue(s/a/A/g),...

它将a更改为A,但不包含ddd

答案 1 :(得分:1)

2之间没有值得注意的区别。它们都是无法理解的随机字符序列,在1970年代中期发明awk时已经过时,因此永远不应该使用。 sed用于单个行上的简单替换,即全部。如果您使用的不仅仅是s,g和p(使用-n),那么您使用了错误的工具。不要再浪费你的时间了,只需使用awk:

$ cat tst.awk
/456/ { f=1 }
f {
    if (/ddd/) {
        f=0
    }
    else {
        gsub(/a/,"A")
        gsub(/o/,"Q")
    }
    print
}

$ awk -f tst.awk file
123-fQQ-456
Abc-xx
fQQ-yy
ddd-ao

清晰,简洁,简洁,强大,高效,便携,并且在其他方​​面比同等的sed解决方案更好。

或者如果把所有东西挤到一条线上对你很有吸引力:

$ awk '/456/{f=1}f{if(/ddd/)f=0;else{gsub(/a/,"A");gsub(/o/,"Q")}print}' file
123-fQQ-456
Abc-xx
fQQ-yy
ddd-ao

您可以使用与sed脚本相同的样式编写awk脚本:

$ awk '/456/,/ddd/{if(!/ddd/){gsub(/a/,"A");gsub(/o/,"Q")}print}' file
123-fQQ-456
Abc-xx
fQQ-yy
ddd-ao

然后你得到了使用范围表达式的重复条件(/ddd/两次),这是它们永远不应该被使用的一个原因。幸运的是,与sed不同,awk具有变量,因此您永远不需要编写范围表达式。