0

我有一个这样的文件:

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

这个怎么做?

4

6 回答 6

6

一种解决方案:

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
于 2015-03-04T10:15:11.953 回答
4

您可以使用以下命令处理文件两次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.:打印它们,存储它的编号。在第二次读取文件时,我们只是跳过那些存储的行。

于 2015-03-04T10:05:32.593 回答
3

对于那些不想使用数组的人来说,另一个 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 开头的行

于 2015-03-04T10:26:14.677 回答
3

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
于 2015-03-04T10:17:36.053 回答
2

使用grep

grep "^xxx" File > NewFile && grep -v "^xxx" File >> NewFile

重定向所有以xxxto file开头的行NewFile。然后 grep 查找not starting带有 并附xxx加到的行NewFile

&&在命令之间使用,因此如果前者以错误状态退出,则不会执行。

于 2015-03-04T10:00:13.693 回答
1
sed '/^xxx/!{H;$!d;}
     ${x;s/.//;}' YourFile

使用d行为(循环而不在脚本中进一步)

于 2015-03-04T12:05:30.190 回答