如何使用sed或其他Linux工具有条件地交换两行?

3

我希望交换两行代码,但只有当它们的顺序不正确时才这样做。例如,如果在XML文件中有以下代码行(可以出现在文件的任何位置,不一定是特定位置):

<person>
    <given-name>John</given-name> 
    <surname>Smith</surname>
</person> 

我想要交换第二行和第三行,使其输出为
<person>
    <surname>Smith</surname>
    <given-name>John</given-name> 
</person> 

但仅适用于那些行顺序混乱的文件。有没有一种用sed或其他Linux工具来实现的方法?


不,我希望能够对任意(非数字、非字母顺序)的行执行此操作。 - Jonathan
1
你如何定义“乱序”? - anubhava
为什么不直接强制按照你想要的顺序重新编写文件(而不用担心逻辑)?祝好运。 - shellter
我将编辑这个问题,以便展示无序行的更好示例。基本上,我想要 <姓> 接着 <名>,而不是反过来。 - Jonathan
听起来你需要一套适当的XML解析/处理工具,而不是sed/grep/awk等... - twalberg
显示剩余2条评论
3个回答

2
这可能对你有用(GNU sed);
sed -r '$!N;s/^(\s*<given-name>.*)\n(\s*<surname>.*)/\2\n\1/;P;D' file

每次读取两行,如果组合错误则交换这两行。


1
假设“第4行”和“第3行”是模式,而不是整行:
awk -v first="line 4" -v second="line 3" '
    $0 ~ second { seen_second = 1 } 
    $0 ~ first && ! seen_second {
        this_line = $0
        # assume the second line is the *next* line
        getline
        print
        print this_line
        next
    } 
    1
' file

这不会修改文件。要进行修改,请执行以下操作:
awk '...' file > tempfile &&
mv file file.bak &&
mv tempfile file

0
如果您希望在数据中姓氏出现在名字前面,可以这样做:surname放在given-name之前。
cat file
<person>
    <given-name>John</given-name>
    <surname>Smith</surname>
</person>
<person>
    <surname>Hanson</surname>
    <given-name>Thor</given-name>
</person>

这个 awk 将会在姓和名的顺序错误时进行更改:

awk '/<person>/ {f=NR} f && f+1==NR && /<given-name>/ {a=$0;getline;print $0 RS a;next} 1' file
<person>
    <surname>Smith</surname>
    <given-name>John</given-name>
</person>
<person>
    <surname>Hanson</surname>
    <given-name>Thor</given-name>
</person>

它是如何工作的:

awk '
/<person>/ {                        # if line include <person> do:
    f=NR}                           # do set flag "f" to line record
f && f+1==NR && /<given-name>/ {    # if flag "f" is true and flag "f+1" equal "NR" and line include <given-name> do:
    a=$0                            # set "a" to current line
    getline                         # get next line
    print $0 RS a                   # print current line and previous line
    next}                           # skip to next record
1                                   # print all other lines
    ' file                          # read the file

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接