Sed 如何仅在部分线路上操作

Sed 如何仅在部分线路上操作,sed,Sed,如何使sed仅在生产线的特定部分运行?相反,我如何使sed在线路的特定部分不起作用 示例: "A a A a ( A a ) A ( a A ) a" 例如,如何仅在(和)之间将所有A替换为Ts以获得: "A a A a ( T a ) A ( a T ) a" 并给出下一个示例输入: "F f F f ( F f ) F ( f F ) f" 例如,我如何将所有的Fs替换为Xs,而不是在(和)之间替换为 获得: “X f X f(f)X(f)f” 我搜索了谷歌,但没有找到任何有用的东西。

如何使sed仅在生产线的特定部分运行?相反,我如何使sed在线路的特定部分不起作用

示例:

"A a A a ( A a ) A ( a A ) a"
例如,如何仅在
之间将所有
A
替换为
T
s以获得:

"A a A a ( T a ) A ( a T ) a"
并给出下一个示例输入:

"F f F f ( F f ) F ( f F ) f"
例如,我如何将所有的
F
s替换为
X
s,而不是在
之间替换为 获得:

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

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

  • 仅在它们之间进行FROM和TO操作(在给定线路上的所有事件上)
  • 在他们之间以外的任何地方进行操作
  • FROM和TO相同时的特殊情况(介于“和”或“FOO”和“FOO”等之间) 两个都是1。二,
  • 它可以用于任何操作,不仅仅是替换,还可以用于打印等,比如打印字符串中“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唯一的问题。

    分而治之

    插入新行以分隔段,然后使用新行、行首(
    ^
    )、行尾(
    $
    )和分隔符(本例中为括号)作为定位点和循环。添加的换行将在末尾删除

    $ 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
    
    这可能适用于您(GNU-sed):

    对于情况1,使用循环将
    a
    的内括号替换为
    T

    对于案例2,使用与上述相同的方法将括号内的
    F
    更改为换行符,然后将
    F
    和换行符分别翻译为
    X
    F

    案例3稍微复杂一些,但可以通过两个替代命令完成:

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

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

    我尽了最大努力。我的想法是通过FROM和to(不知何故)将线路分成几段,然后“不知何故”(我还不知道如何)只对偶数或奇数部分或类似的部分进行操作。如果我知道怎么做,我就不会在这里问了。而且,很可能我的分裂想法是错误的。这很难,我以前只在简单的任务中使用sed。谢谢。请给我一些时间看一下。如果我想替换,比如说,由“[”和“]”字符包围的部分周围的所有内容,就像在正则表达式中一样,该怎么办?该任务类似于将普通正则表达式(其中所有“()[]{}|+?”字符都不需要转义)转换为grep或sed表达式,其中必须转义特殊字符。我的意思是,假设下一个sed表达式没有转义字符,那么必须在sed语法中转义这些字符,因为它们是特殊的字符,我想应用在下一个sed程序的周围空间:“s/\([[(){}}+?]\)/\\\1/g”。输入将是相同的“s/([[(){}}+?])/\\\1/g”。我以“^.[$()*+?{\”字符需要用“\”转义的形式维护基本POSIX正则表达式的数据库,使其成为“非特殊”(man 7正则表达式)。我需要一个脚本,将这些正则表达式转换为给定时刻所需的形式,比如说grep(1)形式。然后我需要它,比如说,sed(1)表单,或vi编辑器表单等。手动转换正则表达式是痛苦的,现在db已经增长到相当大的规模。手动转换所有正则表达式,即使在vi这样一个聪明的编辑器中,也是痛苦的。我需要一个脚本来完成这项任务,这是我问这个问题的最初动机。@hex:看看。因为
    sed
    d如果不环顾四周,您所询问的关于嵌套括号和方括号的替换几乎是不可能的。它们可能是用Perl完成的。
    sed -r 's/FOO|BAR/\n&/g;s/[^\n]*(\nBAR[^\n]*)*(\nFOO([^\n]*)\nBAR)?(\nFOO[^\n]*$)?/\3/g' file