如何移动多个文本文件中的行?

如何移动多个文本文件中的行?

您好,假设我有一个如下所示的文件:

x
x
x
A
B
C
1
2
3
D
E
F
x
x
x

以及文件需要是什么样子:

x
x
x
A
B
C
D
E
F
1
2
3
x
x
x

我知道我可以用几sed -i s/search/replace/g行来完成此操作,但我想知道是否有更好、更简单的方法可以在任一方向上x按数字移动行数y

答案1

编辑

echo -e '7,9m12\n,p' | ed -s file.txt

答案2

使用sed(向下移动行,因为这对于流编辑器来说是最简单的):

$ sed '7,9{H;d;}; 12{G;s/\n//;}' <file
x
x
x
A
B
C
D
E
F
1
2
3
x
x
x

您可以将该sed脚本解读为“将第 7 行到第 9 行移至第 12 行之后”。

脚本注释如下:

7,9{            # These are the lines we'd like to move
    H;          # Append them to the hold space (separated by newlines)
    d;          # Delete from pattern space, start next cycle
}
12{             # This is where we'd like to move those lines
    G;          # Append the hold space
    s/\n//;     # Remove the newline that the above command inserted
}
                # (implicit print)

由于行可以通过正则表达式(不仅仅是行号)来寻址,因此以下内容也可以工作(对此特定数据):

sed '/^1/,/^3/{H;d;}; /^F/{G;s/\n//;}' <file

即,“将行从以 开头的行移动1到以 开头的行3到以”开头的行之后F


将上面的直接翻译成awk

awk '/^1/,/^3/ { hold = hold ORS $0; next }
     /^F/      { $0 = $0 hold }
               { print }' <file

使用“行号”(记录号awk):

awk 'NR == 7, NR == 9 { hold = hold ORS $0; next }
     NR == 12         { $0 = $0 hold }
                      { print }' <file

条件NR == 7, NR == 9也可以写成NR >= 7 && NR <= 9

为了 100% 忠实于sed代码,应该读取第二个块,{ $0 = $0 ORS hold; sub(ORS, "", $0) }但是插入输出记录分隔符(默认情况下为换行符)然后立即将其删除有点愚蠢。


要将原始文件替换为上述命令的结果:

sed ...as above... <file >newfile && mv newfile file

或与命令相同的事情awk

sed如果/的输入文件awk无法读取,或者输出文件无法写入,这将使原始文件保持不变。

相关内容