我有一个这样的文件:
aaa.bbb.1.ccc
xxx.bbb.21
mmm.ppp
xxx.eee
mmm.qqqq
xxx.hhh.12.ddd
我想用一个简单的命令(使用,,...)移动从文件顶部开始的所有xxx.行。sedawkgrep
所以我的新文件将如下所示:
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
重定向所有以xxxto file开头的行NewFile。然后 grep 查找not starting带有 并附xxx加到的行NewFile。
它&&在命令之间使用,因此如果前者以错误状态退出,则不会执行。
sed '/^xxx/!{H;$!d;}
${x;s/.//;}' YourFile
使用d行为(循环而不在脚本中进一步)