Scripting question - feed an input file into an if statement line-by-line
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Scripting question - feed an input file into an if statement line-by-line
Hi all,
I am trying to write a script that takes an input file ($FileName) and an intermediate file ($FileName.info) and removes lines from $FileName if the value in $2 of $FileName.info is <75. I can't figure out how to feed only one line of the .info file to the if statement at a time so that it will perceive it as an integer instead of a list. The error I am getting now is ./script.sh: line 6: [: : integer expression expected
<edit>Just had a thought... maybe your awk is grabbing something that can't be interpreted as a number, try checking the value of $percent_difference before the 'if' test </edit>
<edit2>Second thought... your values in filename.info appear to be 'real' numbers not integers ... </edit2>
#!/bin/bash
declare -a arr
while read -r line
do
set -- $line
num=$2;tag=$1
IFS="."; set -- $num
whole=$1
if [ "$whole" -lt 75 ];then
arr+="$tag"
fi
unset IFS
done <"file.info"
exec 4<"file"
while read -r line <&4
do
case "$line" in
">"*)
flag=0
IFS="|"
set -- $line
for i in ${arr[@]}
do
if [ "$i" = "$3" ];then
flag=1
fi
done
esac
[ "$flag" -eq 1 ] && continue
echo "==>$line"
read NEXT <&4
echo "--->$NEXT"
done
exec 4<&-
The script works perfectly on the sample input data I posted but when I tried it on real data, it didn't work. Any ideas? The organization of the file (including line breaks in the lines not containing greater-than symbols) is the same.
Edit: for reasons unknown to me, the spacing in "file" looks different but I think this is a copy/paste error. The file I am using looks fine. I have checked to make sure that it has unix linebreaks (as did the test file).
if you don't tell me why it doesn't work, how am i going to know?? i ran it with your real data, which you should have provided in the first place, and it runs fine. what errors you got? describe them as much as you can ...
Interesting. I thought the data I provided originally would be a good enough proxy for the real deal but evidently not. The script did not return any errors but it didn't remove the first sequence which has a value in the .dist file >75.
I tried to modify ghostdog74's script to be iterative for all files in a folder but I'm having some trouble. It works on the first file but it makes no changes to the following files. Any ideas what I'm doing wrong?
Code:
#!/bin/bash
for FileName in *.fa
do
infoalign -only -name -change -sequence $FileName -outfile $FileName.info
unset arr
declare -a arr
while read -r line
do
set -- $line
num=$2;tag=$1
IFS="."; set -- $num
whole=$1
if [ "$whole" -gt 75 ];then
arr+=($tag)
fi
unset IFS
done < $FileName.info
exec 4< $FileName
while read -r line <&4
do
case "$line" in
">"*)
flag=0
IFS="|"
set -- $line
for i in ${arr[@]}
do
if [ "$i" = "$3" ];then
flag=1
fi
done
esac
[ "$flag" -eq 1 ] && continue
echo "$line" >> $FileName.trimmed
read NEXT <&4
echo "$NEXT" >> $FileName.trimmed
done
exec 4<&-
done
As I understand it, you are comparing an int to a non-int. bash cannot compare non-int values, use bc as advised above.
Also
Code:
Using the [[ ... ]] test construct, rather than [ ... ] can prevent
many logic errors in scripts. For example, the &&, ||, <, and > operators
work within a [[ ]] test, despite giving an error within a [ ] construct.
Thanks Chris. The script ghostdog wrote truncates the decimal number in the second field of the .info file to the nearest whole number before it is passed to if so I didn't think that was the problem. The double vs. single bracket issue is news to me so I will look into this now. Also, I forgot to mention that I tried kbp and catkin's suggestion of removing the double quotes around the variable in the if statements but this didn't seem to have an effect.
I played around with it a lot this morning and I seem to have it working and behaving properly now. I tried unsetting all of the variables before the declare statement and that seems to have done the trick.
Code:
#!/bin/bash
for FileName in *.fa
do
infoalign -only -name -change -sequence $FileName -outfile $FileName.info
unset arr
unset line
unset num
unset tag
unset whole
unset IFS
declare -a arr
while read -r line
do
set -- $line
num=$2;tag=$1
IFS="."; set -- $num
whole=$1
#echo $FileName
#echo $whole
if [ $whole -gt 75 ];then
arr+=($tag)
fi
unset IFS
done < $FileName.info
exec 4< $FileName
while read -r line <&4
do
case "$line" in
">"*)
flag=0
IFS="|"
set -- $line
for i in ${arr[@]}
do
if [ "$i" = "$3" ];then
flag=1
fi
done
esac
[ $flag -eq 1 ] && continue
echo "$line" >> $FileName.trimmed
read NEXT <&4
echo "$NEXT" >> $FileName.trimmed
done
exec 4<&-
done
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.