我有一个这样的文件:
aaa.bbb.1.ccc
xxx.bbb.21
mmm.ppp
xxx.eee
mmm.qqqq
xxx.hhh.12.ddd
我想用一个简单的命令(使用,,...)移动从文件顶部开始的所有xxx.
行。sed
awk
grep
所以我的新文件将如下所示:
xxx.bbb.21
xxx.eee
xxx.hhh.12.ddd
aaa.bbb.1.ccc
mmm.ppp
mmm.qqqq
这个怎么做?
一种sed解决方案:
sed -n '/^xxx/! { H }; // p; $ { x; s/^\n//; p }' infile
将H
不以开头的内容附加xxx
到保持空间,并立即打印相反的匹配项// p
。最后一行$
恢复保留空间内容,删除前导换行符并打印。
它产生:
xxx.bbb.21
xxx.eee
xxx.hhh.12.ddd
aaa.bbb.1.ccc
mmm.ppp
mmm.qqqq
您可以使用以下命令处理文件两次awk
:
$ awk 'FNR==NR {if (/^xxx\./) {print; a[FNR]} next} !(FNR in a)' file file
xxx.bbb.21
xxx.eee
xxx.hhh.12.ddd
aaa.bbb.1.ccc
mmm.ppp
mmm.qqqq
在第一个中,我们匹配以 and 开头的行xxx.
:打印它们,存储它的编号。在第二次读取文件时,我们只是跳过那些存储的行。
对于那些不想使用数组的人来说,另一个 awk:
$ awk 'NR == FNR { if (/^xxx/) print; next } !/^xxx/' top.txt top.txt
xxx.bbb.21
xxx.eee
xxx.hhh.12.ddd
aaa.bbb.1.ccc
mmm.ppp
mmm.qqqq
NR == FNR { if (/^xxx/) print; next }
第一遍,打印以 xxx 开头的行
!/^xxx/
第二遍,打印不以 xxx 开头的行
Another awk
awk '!/^xxx/ {a[$0];next} 1; END {for (i in a) print i}' file
xxx.bbb.21
xxx.eee
xxx.hhh.12.ddd
aaa.bbb.1.ccc
mmm.ppp
mmm.qqqq
!/^xxx/
If line does not start with xxx
a[$0];next
store it in array a
1
print line with xxx
END {for (i in a) print i}
At end print lines in array a
. (the one without xxx
)
As fedorqui (thank you) points out, if order of lines are important, use this:
awk '!/^xxx/ {a[++c]=$0;next} 1; END {for (i=1;i<=c;i++) print a[i]}' file
xxx.bbb.21
xxx.eee
xxx.hhh.12.ddd
aaa.bbb.1.ccc
mmm.ppp
mmm.qqqq
使用grep:
grep "^xxx" File > NewFile && grep -v "^xxx" File >> NewFile
重定向所有以xxx
to file开头的行NewFile
。然后 grep 查找not starting
带有 并附xxx
加到的行NewFile
。
它&&
在命令之间使用,因此如果前者以错误状态退出,则不会执行。
sed '/^xxx/!{H;$!d;}
${x;s/.//;}' YourFile
使用d
行为(循环而不在脚本中进一步)