Reputation: 43558
I have a file like this:
aaa.bbb.1.ccc
xxx.bbb.21
mmm.ppp
xxx.eee
mmm.qqqq
xxx.hhh.12.ddd
I want to move all the lines starting with xxx.
at the top of the file with a simple command (using sed
, awk
, grep
...).
So my new file will look like this:
xxx.bbb.21
xxx.eee
xxx.hhh.12.ddd
aaa.bbb.1.ccc
mmm.ppp
mmm.qqqq
How to do this?
Upvotes: 0
Views: 976
Reputation: 10039
sed '/^xxx/!{H;$!d;}
${x;s/.//;}' YourFile
using the d
behaviour (cycle without going further in script)
Upvotes: 1
Reputation: 41460
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
Upvotes: 3
Reputation: 5298
With grep:
grep "^xxx" File > NewFile && grep -v "^xxx" File >> NewFile
Redirect all lines starting with xxx
to file NewFile
. Then grep for lines not starting
with xxx
and append to NewFile
.
It uses &&
between commands, so that one is not executed if the former exited with the bad status.
Upvotes: 2
Reputation: 10865
Another awk for those not in the mood to use arrays:
$ 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 }
First pass, print lines starting with xxx
!/^xxx/
Second pass, print lines not starting with xxx
Upvotes: 3
Reputation: 36282
One sed solution:
sed -n '/^xxx/! { H }; // p; $ { x; s/^\n//; p }' infile
The H
appends the content that does not begin with xxx
to the hold space, and the opposite match is printed inmediatly // p
. At last line $
recover the hold space contents, remove leading newline character and print.
It yields:
xxx.bbb.21
xxx.eee
xxx.hhh.12.ddd
aaa.bbb.1.ccc
mmm.ppp
mmm.qqqq
Upvotes: 6
Reputation: 290155
You can process the file twice with 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
In the first one, we match the lines starting with xxx.
and: print them, store its number. In the second reading of the file, we just skip those stored lines.
Upvotes: 4