如何仅在部分线路上操作

时间:2010-12-14 14:57:32

标签: sed

如何仅对线路的特定部分进行操作?而且,相反,我如何使sed不能在一行的特定部分上工作?

示例:

"A a A a ( A a ) A ( a A ) a"

例如,如何在AT之间仅用( s 替换所有)以获取:

"A a A a ( T a ) A ( a T ) a"

并给出下一个示例输入:

"F f F f ( F f ) F ( f F ) f"

例如,我如何在FX之间用(替换所有)而不是 获得:

  

“X f X f(F f)X(f F)f”

我搜索了谷歌,但没有发现任何可用的内容我想这是关于sed的一般性问题。我希望这个问题可以简化为一般的“模板”。

  1. 让FROM和TO仅在它们之间操作(在给定行的所有事件中)
  2. 让FROM和TO在他们之间的任何地方运作......
  3. FROM和TO相同时的特殊情况(“和”或“FOO”和“FOO”之间等) 对于1.和2。
  4. 它应该适用于任何操作,不仅仅是替换,还可以用于打印等,比如在字符串“FOO”和“BAR”之间打印所有内容。

    "1 2 3 BAR a b c FOO d e f BAR g a h FOO i j k BAR l m n FOO o p q"
    

    结果将是

    " d e f  i j k "
    

    因此,我们将非常感谢有关如何操作的一般示例。似乎这个问题很常见,但谷歌还没有找到好的方法。我也猜这个 回答是非常具有挑战性的。请不要给出任何关于如何做的提示 使用Perl,AWK或除sed之外的任何其他东西。这个问题实际上只是一个sed问题。

2 个答案:

答案 0 :(得分:1)

分而治之。

插入换行符以分隔段然后使用换行符,行开头(^),行结束($)和分隔符(本例中为圆括号)作为锚点和循环。最后删除了添加的换行符。

$ echo "A a A a ( A a ) A ( a A ) a" |
    sed 's/([^)]*)/\n&/g; 
         :a; 
           s/\(\n([^)]*\)A\([^)]*)\)/\1T\2/;
         ta; 
         s/\n//g'
A a A a ( T a ) A ( a T ) a
$ echo "F f F f ( F f ) F ( f F ) f" | 
    sed 's/(/\n(/g; 
         s/)/)\n/g; 
         :a; 
           s/\([^(]*\)F\([^)]*\(\n\|$\)\)/\1X\2/g; 
         ta; 
         s/\n//g'
X f X f ( F f ) X ( f F ) f
$ echo "1 2 3 BAR a b c FOO d e f BAR g a h FOO i j k BAR l m n FOO o p q" | 
    sed 's/^/BAR/;
         s/$/FOO/;
         s/FOO/&\n/g;
         s/BAR/\n&/g;
         s/BAR[^\n]*\n//g;
         s/[^\n]*FOO\n//g;
         s/\n//g'
 d e f  i j k

答案 1 :(得分:1)

这可能适合你(GNU sed):

sed ':a;s/\(([^)]*\)A/\1T/;ta' file # for case 1

sed ':a;s/\(([^)]*\)F/\1\n/;ta;y/F\n/TF/' file  # for case 2

对于案例1,使用循环将括号内的A替换为T

对于案例2,使用与上述相同的内容将括号内的F更改为换行符,然后将F和换行符翻译为X&# 39; s和F分别为。

案例3涉及更多,但可以用2个替代命令完成:

sed -r 's/FOO|BAR/\n&/g;s/[^\n]*(\nBAR[^\n]*)*(\nFOO([^\n]*)\nBAR)?(\nFOO[^\n]*$)?/\3/g' file

首先在每个FOOBAR字符串前加上换行符。然后查找FOOBAR的所有组合,并将字符串保留在FOOBAR之间。换行符允许使用否定类来简化过程。