Homap
Homap

Reputation: 2214

parse and echo string in a bash while loop

I have a file with this structure:

picture1_123.txt
picture2_456.txt
picture3_789.txt
picture4_012.txt

I wanted to get only the first segment of the file name, that is, picture1 to picture4. I first used the following code:

cat picture | while read -r line; do cut -f1 -d "_"; echo $line; done

This returns the following output:

picture2
picture3
picture4
picture1_123.txt

This error got corrected when I changed the code to the following:

cat picture | while read line; do s=$(echo $line | cut -f1 -d "_"); echo $s; done

picture1
picture2
picture3
picture4

Why in the first:

  1. The lines are printed in a different order than the original file?
  2. no operation is done on picture1_123.txt and picture1 is not printed?

Thank you!

Upvotes: 1

Views: 257

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295403

What Was Wrong

Here's what your old code did:

  • On the first (and only) iteration of the loop, read line read the first line into line.
  • The cut command read the entire rest of the file, and wrote the results of extracting only the desired field to stdout. It did not inspect, read, or modify the line variable.
  • Finally, your echo $line wrote the first line in entirety, with nothing being cut.
  • Because all input had been consumed by cut, nothing remained for the next read line to consume, so the loop never ran a second time.

How To Do It Right

The simple way to do this is to let read separate out your prefix:

while IFS=_ read -r prefix suffix; do
  echo "$prefix"
done <picture

...or to just run nothing but cut, and not use any while read loop at all:

cut -f1 -d_ <picture

Upvotes: 2

Related Questions