您好,假设我有一个如下所示的文件:
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
无法读取,或者输出文件无法写入,这将使原始文件保持不变。