MOHAMED
MOHAMED

Reputation: 43558

How to move some lines to the top of the file?

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

Answers (6)

NeronLeVelu
NeronLeVelu

Reputation: 10039

sed '/^xxx/!{H;$!d;}
     ${x;s/.//;}' YourFile

using the d behaviour (cycle without going further in script)

Upvotes: 1

Jotne
Jotne

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

Arjun Mathew Dan
Arjun Mathew Dan

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

jas
jas

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

Birei
Birei

Reputation: 36282

One 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

fedorqui
fedorqui

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

Related Questions