1

I have a text file like this.

 res          ABS   sum     
 SER A   1   161.15 138.3  
 CYS A   2    66.65  49.6  
 PRO A   3    21.48  15.8  
 ALA A   4    77.68  72.0  
 ILE A   5    15.70   9.0  
 HIS A   6    10.88   5.9 

I would like to extract the names of first column(res) based on the values of last column(sum). I have to print resnames if sum >25 and sum<25. How can I get the output like this?

1
  • Per the conversation in the comments, can you clarify when you actually want resnames printed? No number can be both less than 25 and greater than 25. Do you want resnames printed if sum != 25, or do you want it printed if, for instance, sum < 25 OR ABS > 25? Commented Apr 28, 2012 at 15:28

5 Answers 5

1

This should do it:

awk 'BEGIN{FS=OFS=" "}{if($5 != 25) print $1}' bla.txt
Sign up to request clarification or add additional context in comments.

Comments

1

While you can do this with a while read loop in bash, it's easier, and most likely faster, to use awk

awk '$5 != 25 { print $1 }'

Note that your logic print resnames if sum >25 and sum<25 is the same as print if sum != 25.

4 Comments

Sum > 25 and sum < 25 leaves nothing. Or would.
@TimPote: So 25 is meanwhile > 25 and < 25?
@userunknown Ah I see. Apply actual boolean logic. Sorry I parsed that as what he meant not what he actually said. Yeah actual boolean logic would say that he needs to print nothing.
Mh, yes, but what he meant might be two functions, one which selects the lower, and one which selects the higher values, but not both at the same time. However - from your sample code it is trivial to make 2 specialized ones. What's about the headline?
1

Consider using awk. Its a simple tool for processing columns of text (and much more). Here's a simple awk tutorial which will give you an overview. If you want to use it within a bash script, then this tutorial should help.

Run this on the command line to give you an idea of how you could do it:

> echo "SER A   1   161.15 138.3" | awk '{ if($5 > 25) print $1}'
> SER
> echo "SER A   1   161.15 138.3" | awk '{ if($5 > 140) print $1}'
> 

Comments

0
while read line
do 
v=($line)
sum=${v[4]}
((${sum/.*/} >= 25)) && echo ${v[0]}
done < file

You need to skip the first line.

Since bash doesn't handle floating point values, this will print 25 which isn't exactly bigger than 25.

This can be handled with calling bc for arithmetics.

tail -n +2 ser.dat | while read line
do  
  v=($line)
  sum=${v[4]}
  gt=$(echo "$sum > 25" | bc) && echo ${v[0]}
done

Comments

0

what about the good old cut? :)

say you would like to have the second column,

cat your_file.txt | sed 's, +, ,g' | cut -d" " -f 2

what is doing sed in this command? cut expects columns to be separated by a character or a string of fixed length (see documentation).

1 Comment

Just to let you know, there are a few problems with this solution. First of all, it's a prime example of a Useless Use of Cat. sed can work on files without the need for the pipe. Second, awk doesn't have the field separator limitations of cut, so you could do the same with a single print $2 in awk without the need for sed. Third, it doesn't do what the OP asks. They wanted to conditionally print the second field. Yours always prints the second field.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.