LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   BASH: rearrange lines in a file by line number & print in that order (https://www.linuxquestions.org/questions/linux-newbie-8/bash-rearrange-lines-in-a-file-by-line-number-and-print-in-that-order-904044/)

SilversleevesX 09-20-2011 12:46 PM

BASH: rearrange lines in a file by line number & print in that order
 
Here's what I've tried with sed and here's what I'm getting.

From this list in a file called "baseball"
Code:

Bats
Balls
Bases
Caps
Mitts
Uniforms

if I try
Code:

sed -n -e '1p;' -e '3p;' baseball
I get
Code:

Bats
Bases

but if I should add another line number, as I did here
Code:

sed -n '2p; 4p; 1p' baseball
I get
Code:

Bats
Balls
Caps

which are the right lines, just not in the order I asked for them. When I add another line number reference (e.g: 5p), it returns the first four lines in the file, but not line 5, which is what I asked for.

I'm thinking that because sed processes things in a stream (hence the name), and can find and return single lines, line pairs and ranges, it can't do anything as fancy as return many lines by their line number in any order that "goes against the stream."

So what does do this?

Or better, what would be a better way of reading in lines like the ones in baseball, and returning them in a "custom" order?

BZT

macemoneta 09-20-2011 01:38 PM

You can do something like this:
Code:

# Load the file into an array
mapfile -t someArray < someFile

# Display records 2, 4, and 1 in order
for i in 2 4 1 ;do
  echo "${someArray[$i]}"
done


SilversleevesX 09-20-2011 03:25 PM

That almost works.

I added the word "Catchers" to the data file, and tried to use it to print every line in an arbitrary order
Code:

mapfile -t someArray <baseball
for i in 6 3 2 4 5 1 ; do echo "${someArray[$i]}"; done

The result was
Code:

Catchers
Caps
Bases
Mitts
Uniforms
Balls

That looked satisfactory. So I tried it on another 6-line text file
Quote:

Adele,25
Gemma J,24
Eloise,25
McKenzie,25
Annabella,23
Lana C,28
using something other than someArray as my variable.
Code:

mapfile -t cuteAussies <girls-image07.txt
for i in 6 3 2 4 5 1 ; do echo "${cuteAussies[$i]}"; done

This gave me
Quote:


McKenzie,25
Eloise,25
Annabella,23
Lana C,28
Gemma J,24
Here you'll notice there's no 6th line, but a blank line instead. There's also one missing from the set in the for/do/done loop, and as a result the lines that do appear aren't in the order I "requested."

Why should that be? Could the source data text file be corrupt, or is there another possibility?

BZT

macemoneta 09-20-2011 04:05 PM

The index is zero-based by default, and for lines with embedded spaces, you don't want the '-t' option (it would help to read the bash man page).

David the H. 09-20-2011 05:11 PM

Yes, sed operates sequentially from start to finish. It reads in one line at a time and attempts to apply all the given expressions to them. So the output of the OP examples will always be in the order that they appear in the file.

SilversleevesX 09-20-2011 05:24 PM

Quote:

Originally Posted by macemoneta (Post 4477514)
The index is zero-based by default, and for lines with embedded spaces, you don't want the '-t' option (it would help to read the bash man page).

I get you: 0 through 5 (or what have you) not 1 through 6 (likewise).

I'll try that.

BZT

chrism01 09-20-2011 06:06 PM

Yeah, its historical.
Basically way back (1970 - ish), after a couple of attempts in various langs, Unix was re-written in C, and C arrays begin at zero because they are defined as mem_address + offset.
Most tools/langs developed on *nix follow the same pattern.

grail 09-20-2011 07:31 PM

You could do the same process as mapfile / for loop with awk. Simply save all the data and then print the order you like.
If you use NR as the index you will also be able to use 1 to 6 for the line numbers.


All times are GMT -5. The time now is 09:55 AM.