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

时间:2014-04-23 19:38:07

标签: linux bash sed

我想交换两行,但前提是它们的顺序错误。例如,如果我有XML行(文件中的任何位置,在某些位置不需要),如下所示:

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

我想交换第二行和第三行,以便生成

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

但仅限于那些行无序的文件。有没有办法用sed或其他linux工具做到这一点?

3 个答案:

答案 0 :(得分:1)

这可能适合你(GNU sed);

sed -r '$!N;s/^(\s*<given-name>.*)\n(\s*<surname>.*)/\2\n\1/;P;D' file

一次读取2行,如果组合错误则交换行。

答案 1 :(得分:0)

假设&#34;第4行&#34;和&#34;第3行&#34;是模式而不是整行:

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

答案 2 :(得分: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会更改surnamegiven-name的顺序:

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