交换两行

gho*_*g74 11 sed

我怎样才能利用SED的H,h,x,g,G等命令来交换两行呢?

例如在文件中

START
this is a dog
this is a cat
this is something else
END
Run Code Online (Sandbox Code Playgroud)

说我想用"这是别的东西"交换"这是一只狗".

这是我到目前为止:

/this is a dog/{
 h # put to hold space 
}
/this is something else/{
 # now i am stuck on what to do.
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*ce. 22

如果您知道要交换的两行中的每一行上的模式,但不知道行的完整内容,则可以执行以下操作:

sed -n '                     # turn off default printing
    /dog/{                   # if the line matches "dog"
           h                 # put it in hold space
           :a                # label "a" - the top of a loop
           n                 # fetch the next line
           /something/{      # if it matches "something"
                       p     # print it
                       x     # swap hold and pattern space
                       bb    # branch out of the loop to label "b"
           }                 # done with "something"
                             # if we're here, the line doesn't match "something"
           H                 # append pattern space to hold space
           x                 # swap hold and pattern space
           s/\([^\n]*\)\n\([^\n]*\)$/\2\n\1/    # see below
           x                 # swap hold and pattern space
           ba                # branch to the top of the loop to label "a"
    }                        # done with "dog"
    :b                       # label "b" - outside the loop
                             # print lines that don't match and are outside the pair
    p                        # also prints what had been accumulating in hold space
    ' inputfile
Run Code Online (Sandbox Code Playgroud)

替换模式将"狗"保持在累积行的末尾.它不断交换我们保留在空间中的最后两行,以便"狗""气泡"到底部.

例如,让我们在"cat"行之后添加另一行,这样过程就会更加清晰.我们将忽略"狗"之前和"某事"之后的界限.我将继续使用我的昵称来引用这些行

this is a dog
this is a cat
there's a bear here, too
this is something else
Run Code Online (Sandbox Code Playgroud)

读取"狗",然后取出"猫".一些追加和交换已完成.现在模式空间看起来像这样(\N代表换行符,我使用大写"N",因此它突出,它^是模式空间的开始,$是结束):

^this is a dog\Nthis is a cat$
Run Code Online (Sandbox Code Playgroud)

替换命令查找不是换行符(并捕获它们)的任意数量的字符,后跟换行符后跟任意数量的非换行符(并捕获它们)的行,这些符号位于行的末尾($)并替换所有这两个捕获的字符串以相反的顺序由换行符分隔.现在模式空间如下所示:

^this is a cat\Nthis is a dog$
Run Code Online (Sandbox Code Playgroud)

现在我们交换并读取一个新行.它不是"东西"所以我们做一些追加和交换,现在我们有:

^this is a cat\Nthis is a dog\Nthere's a bear here, too$
Run Code Online (Sandbox Code Playgroud)

我们再次进行替换并得到:

^this is a cat\Nthere's a bear here, too\Nthis is a dog$
Run Code Online (Sandbox Code Playgroud)

为什么我们不换"熊/狗/猫"呢?因为由两行组成的正则表达式模式(每个通常由非换行符后跟一个换行符组成)使用它锚定在行的末尾,$所以我们忽略了它之前的任何内容.请注意,最后一个换行是隐含的,并且实际上不存在于模式或保留空间中.这就是为什么我不在这里展示它.

现在我们读"东西"并打印出来.我们交换.嘿! 那些我们一直在"冒泡"的东西.分支和打印.由于"狗"位于线的底部(已经在保留空间中积累)并且我们在那一堆之前打印了"某物",效果是我们交换了两条线.

无论在要交换的两行之前,之间或之后出现多少行,此脚本都将起作用.实际上,如果存在多对匹配行,则每对中的成员将在整个文件中交换.

正如你所看到的,我只关注感兴趣的一行中的一个词,但任何合适的正则表达式都可以.