我有重复的sed命令,它们会切换第1行,第2行,第3行和第4行,等等。但是,当我尝试将它们合并时,它会添加重复的行并消除一些行。
编辑:
sed之前的原始文件如下:
Some code....
Some code...
Line-a
Line-b
Line-c
Line-d
Line-e
Line-f
some more...
some more...
提供所需输出的代码是:
sed -i '2{h;d};3{p;x}' file.txt && sed -i '4{h;d};5{p;x}' file.txt && sed -i '6{h;d};7{p;x}' file.txt
我想使用的代码是:
sed -i '2{h;d};3{p;x};4{h;d};5{p;x};6{h;d};7{p;x}' file.txt
从订购的文件中获得所需的输出
Some code...
Some code...
Line-b
Line-a
Line-d
Line-c
Line-f
Line-e
some more...
some more...
答案 0 :(得分:4)
除非您使用的是GNU sed,否则( $!)除非当前行是文件的最后一行,否则( x )交换模式空间的内容并保持空格( n )将新行读入模式空间,( G )通过换行符将保留空间的内容追加到模式空间。 ( p )打印图案空间的内容。
$ cat file
one
two
three
four
five
six
seven
$
$ sed -n -i '$!{x;n;G};p' file
$
$ cat file
two
one
four
three
six
five
seven
要使其与POSIX具有100%的兼容性,您需要放弃就地编辑并将脚本分成多个命令:
sed -n -e '$!{x;n;G;}' -e 'p' file
这回答了the first version of OP's question。由于他们的最新编辑变得难以理解,因此我拒绝编辑。
答案 1 :(得分:4)
这对于sed是完全不合适的任务。只需使用awk,例如使用GNU awk进行“就地”编辑,因为出于某种原因,这似乎是一个优先事项,并且使用了经过修改的示例输入文件,因此可以清楚地知道哪些行和哪些行不会被交换:
$ cat file
with a some code here
and a some code there
Line-a
Line-b
Line-c
Line-d
Line-e
Line-f
here a code, there a code
everywhere a code, code
$ awk -i inplace 'NR>=3 && NR<=8{if ((++c)%2) p=$0; else print $0 ORS p; next} 1' file
$ cat file
with a some code here
and a some code there
Line-b
Line-a
Line-d
Line-c
Line-f
Line-e
here a code, there a code
everywhere a code, code
除了仅使用GNU的-i inplace
语法糖而不是> tmp && mv tmp file
之外,该脚本将在任何UNIX机器上的任何shell中使用任何awk进行工作。
原始回复和下面的其他示例:
$ awk 'NR%2{p=$0;next} {print $0 ORS p}' file
Some code...
Some code...
Line-b
Line-a
Line-d
Line-c
Line-f
Line-e
以上内容可在任何UNIX盒中的任何shell中使用任何awk进行工作。
只想在第4行和第7行之间交换吗?这是微不足道的调整,因为这是完成任务的正确工具:
$ seq 10 | awk 'NR<=3 || NR>=8{print; next} (++c)%2{p=$0;next} {print $0 ORS p}'
1
2
3
5
4
7
6
8
9
10
或者,如果您愿意:
$ seq 10 | awk 'NR>=4 && NR<=7{if ((++c)%2) p=$0; else print $0 ORS p; next} 1'
1
2
3
5
4
7
6
8
9
10
是否想每3行反转一次?同样,这很简单,因为这是完成任务的正确工具:
$ seq 9 | awk 'NR%3{p2=p1;p1=$0;next} {print $0 ORS p1 ORS p2}'
3
2
1
6
5
4
9
8
7
希望您能得到图片...
答案 2 :(得分:2)
这可能对您有用(GNU sed):
sed '3,8{N;s/\(.*\)\n\(.*\)/\2\n\1/}' file
对于一系列行,请追加以下行,并使用模式匹配将它们交换。
如果要交换,请说第3-4行和第7-8行:
sed '3ba;7ba;b;:a;N;s/\(.*\)\n\(.*\)/\2\n\1/' file
或交换3-5和6-8行,使用:
sed '3,8{N;N;s/\(.*\)\n\(.*\)\n\(.*\)/\3\n\2\n\1/} file
答案 3 :(得分:1)
对于这个问题,有一个可以说更简单的GNU sed解决方案 1 :
1,2b # In the range 1,2 ...
9,$b # ... and also in 9,$, auto print and end this cycle.
3~2 { # From line 3 and every second line thereafter,
h # hold, then
d # delete, and end this cycle.
}
G # On every other line, append hold space and auto print.
测试:
# test.sh
cat > FILE <<EOF
Some code....
Some code...
Line-a
Line-b
Line-c
Line-d
Line-e
Line-f
Some more code...
Some more code...
EOF
sed '1,2b; 9,$b; 3~2{h;d}; G' FILE
输出:
Some code....
Some code...
Line-b
Line-a
Line-d
Line-c
Line-f
Line-e
Some more code...
Some more code...
请注意,通过first~step
选择行,例如3~2
是GNU扩展。
这是基于Chap中交换行的一般示例。 O'Reilly sed和awk第二版的6。
1 但我同意Ed Morton的评论,即AWK更适合解决此问题。