交换两行 [英] Swapping two lines

查看:49
本文介绍了交换两行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用sed H, h, x, g, G 等命令交换两行?

How can I make use of the sed H, h, x, g, G etc. commands to swap two lines?

例如在文件中

START
this is a dog
this is a cat
this is something else
END

说我想把这是一只狗"换成这是别的东西".

say I want to swap "this is a dog" with "this is something else".

这是我目前所拥有的:

/this is a dog/{
 h # put to hold space 
}
/this is something else/{
 # now i am stuck on what to do.
}

推荐答案

如果您知道要交换的两行中每一行的模式,但不知道这些行的全部内容,您可以执行以下操作:

If you know a pattern on each of the two lines you want to swap, but not the full contents of the lines, you can do something like this:

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

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

The substitution pattern keeps "dog" at the end of the accumulated lines. It keeps swapping the last two lines that we're keeping in hold space so that "dog" "bubbles" to the bottom.

例如,让我们在cat"行之后再添加一行,这样过程会更清晰一些.我们将忽略dog"之前和something"之后的行.我将继续使用我的昵称来引用这些行

For example, let's put another line after the "cat" line so the process is a little clearer. We'll ignore the lines before "dog" and after "something". And I'll continue to refer to the lines using my nicknames

this is a dog
this is a cat
there's a bear here, too
this is something else

读取狗",然后获取猫".完成了一些附加和交换.现在模式空间看起来像这样(\N 代表一个换行符,我使用大写的N"所以它很突出,^ 是模式的开始空格和 $ 是结尾):

"Dog" is read, then "cat" is fetched. Some appending and swapping is done. Now pattern space looks like this (\N represents a newline, I'm using an upper case "N" so it stands out, the ^ is the beginning of the pattern space and $ is the end):

^this is a dog\Nthis is a cat$

替换命令查找任意数量的不是换行符的字符(并捕获它们),然后是一个换行符,然后是任意数量的位于行尾的非换行符(并捕获它们)的字符($) 并用换行符分隔的相反顺序用两个捕获的字符串替换所有这些.现在模式空间看起来像这样:

The substitution command looks for any number of characters that are not newlines (and captures them) followed by a newline followed by any number of characters that are not newlines (and captures them) that are at the end of the line ($) and replaces all that with the two captured strings in the reverse order separated by a newline. Now pattern space looks like this:

^this is a cat\Nthis is a dog$

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

Now we swap and read a new line. It's not "something" so we do some appending and swapping and now we have:

^this is a cat\Nthis is a dog\Nthere's a bear here, too$

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

We do the substitution again and get:

^this is a cat\Nthere's a bear here, too\Nthis is a dog$

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

Why didn't we get "bear/dog/cat" instead? Because the regex pattern consisting of two lines (which each, as usual, consist of non-newlines followed by a newline) is anchored at the end of the line using the $ so we're ignoring anything that comes before it. Note that the last newline is implied and doesn't actually exist in pattern or hold space. That's why I'm not showing it here.

现在我们读取某物"并打印出来.我们交换.嘿!有些东西我们一直在冒泡".分支并打印.由于dog"位于行的底部(已累积在保持空间中)并且我们在该行之前打印了something",因此我们交换了两行.

Now we read "something" and print it. We swap. Hey! there's that stuff that we've been "bubbling". Branch and print. Since "dog" is at the bottom of the lines (that had been accumulated in hold space) and we printed "something" right before that bunch, the effect is that we swapped the two lines.

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

This script will work regardless of how many lines appear before, between or after the two lines to be swapped. In fact, if there are multiple pairs of matching lines, the members of each pair will be swapped throughout the file.

如您所见,我只键入感兴趣的行中的一个单词,但任何合适的正则表达式都可以.

As you can see, I'm keying on just one word in the lines of interest, but any suitable regular expression would do.

这篇关于交换两行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆