check if a file contains two variables in a line - bash

I am trying to check the values of my variables are exist in the file or not using if condition in Bash.
I tried is as follows, but for all the values I am getting value false.
a=-127.5256
b=24.5632
file=test.txt
-54.2565 58.9685
-127.2568 12.5890
-127.5256 24.5632
-78.9865 35.2366
I tried as follow but not working in my case:
if grep -Fxq "($a $b | bc)" $file; then
echo True
else
echo False
Is there any other way to perform the above job?
Thank you

I would prefer to use AWK.
awk -v a=-127.5256 -v b=24.5632 '{if ($1==a && $2=b) print "True"}' < input file
using bash
while IFS=" " read -r f1 f2;
do
if [ "$a" == "$f1" ] && [ "$b" == "$f2" ]
then
echo "True"
fi
done < input file
Demo:
$cat test.txt
-54.2565 58.9685
-127.2568 12.5890
-127.5256 24.5632
-78.9865 35.2366
$awk -v a=-127.5256 -v b=24.5632 '{if ($1==a && $2=b) print "True"}' test.txt
True
$echo $a $b
-127.5256 24.5632
$while IFS=" " read -r f1 f2;
> do
> if [ "$a" == "$f1" ] && [ "$b" == "$f2" ]
> then
> echo "True"
> fi
> done < test.txt
True
$

Related

Awk: Print specific value range

Say i have:
> id|lastName|firstName|gender|birthday|creationDate|locationIP|browserUsed
>
> 13194139534963|Berty|Jean|male|1988-08-02|2012-04-02T08:33:15.012+0000|41.216.190.153|Google
> Chrome
>
> 13194139535544|Oliveira|Manuel|male|1984-10-31|2012-03-14T16:00:12.287+0000|109.71.166.230|Internet
> Explorer
>
> 13194139537327|Wei|Lei|male|1987-01-06|2012-03-13T03:07:51.899+0000|27.99.188.150|Internet
> Explorer
>
> 13194139539118|Alvarez|Monica|male|1989-10-17|2012-02-25T19:18:54.137+0000|190.169.213.242|Internet
> Explorer
>
> 13194139539746|Xu|Wei|female|1986-11-30|2012-03-19T23:16:12.495+0000|27.103.77.193|Firefox
I want to make a command with those parameters : ./tool.sh --born-since dateA --born-until dateB -f file
1)If born-since and born-until dates are given i want to print all those born(the whole line)between two specific dates ( Year-Month-Date )
Example
./tool.sh --born-since 1988-08-02 --born-until 2012-09-13 -f file
Output:
13194139534963|Berty|Jean|male|1988-08-02|2012-04-02T08:33:15.012+0000|41.216.190.153|Google
13194139539118|Alvarez|Monica|male|1989-10-17|2012-02-25T19:18:54.137+0000|190.169.213.242|Internet
Explorer
2)If only born-since date is given i want to list all the people(whole line) with born dates of that and after.
Example:
./tool.sh --born-since 1988-08-02 -f file
Output:
Same as 1)
3)If only born-until date is given i want to list all the people born until that date(again the whole line about them).
./tool.sh --born-until 1988-08-02 -f file
Output:
13194139535544|Oliveira|Manuel|male|1984-10-31|2012-03-14T16:00:12.287+0000|109.71.166.230|Internet Explorer
13194139537327|Wei|Lei|male|1987-01-06|2012-03-13T03:07:51.899+0000|27.99.188.150|Internet Explorer
13194139539746|Xu|Wei|female|1986-11-30|2012-03-19T23:16:12.495+0000|27.103.77.193|Firefox
My code is :
while [ $# -gt 0 ];do #Get and store Dates (Since-Until)
if [ "$1" = --born-since ];then
if [[ "$2" =~ $re ]];then #re='[0-9]-*' # Check if $2 is number
BSDate=$2
BSYear=$(echo "$BSDate" | awk -F '-' '{print $1}') # Get BSYear
BSMonth=$(echo "$BSDate" | awk -F '-' '{print $2}') # Get BSMonth
BSDay=$(echo "$BSDate" | awk -F '-' '{print $3}') # Get BSDay
fi
elif [ "$1" = --born-until ];then
if [[ "$2" =~ $re ]];then
BUDate=$2
BUYear=$(echo "$BUDate" | awk -F '-' '{print $1}') # Get BUYear
BUMonth=$(echo "$BUDate" | awk -F '-' '{print $2}') # Get BUMonth
BUDay=$(echo "$BUDate" | awk -F '-' '{print $3}') # Get BUDay
fi
fi
shift
done
if [ "$BSDate" ] && [ "$BUDate" ];then #If both date arguments exist
elif [ "$BSDate" ];then
elif [ "$BUDate" ];then
fi
If i enter --born-since 1998-10-30 the arguments get passed correctly for evaluation in awk , 1998 = BSYear , 10 = BSMonth , 30 = BSDay. Can someone help me implement the awk part ?
For the awk part :
cat ./tool.sh
awk -F'|' -vs="$1" -ve="$2" '
BEGIN{if(!s)s="0000-00-00";if(!e)e="9999-99-99"}
NR>1 && $5>=s && $5<=e' infile
And you call it like that
./tool.sh '1987-01-06' '1988-08-02'
or
./tool.sh '' '1988-08-02'
or
./tool.sh '1987-01-06' ''
I fixed it with : awk -F'|' '{if ($5 >= "'$BSDate'" && $5 <= "'$BUDate'")

Why is variable being incremented?

Could someone help me figure why is the variable "$valorbase" in my script being incremented. It should continue the process for the next line when "$valorbase=8", though it happens only for the first line. Then it starts incrementing the numbers and dont stop when value 8 is reached.
Thanks!
#!/bin/bash
while read -r line <&3
do
valorbase=8
valor=0
echo "$line"
echo "Valor:"
read -r valor
echo "$valor" >&5
echo "||||||""$valor""|" >&6
valordasoma=$(awk -F"|" '{ sum += $1 } END { print sum }' < soma.txt)
var=$(awk -v o1=$valordasoma -v t1=$valorbase 'BEGIN { print (o1 >= t1)?"1":"0" }' < soma.txt)
if [[ $var -ge 1 ]]
then
echo "Valor da soma > que, ou = ao valor base"
echo "Repete comando para a linha"
else [[ $var -lt 1 ]]
until [[ $var -eq 1 ]]
do
echo "Valor:"
read -r valor
echo "$valor" >&5
echo "||||||""$valor""|" >&6
valordasoma=$(awk -F"|" '{ sum += $1 } END { print sum }' < soma.txt)
var=$(awk -v o1=$valordasoma -v t1=$valorbase 'BEGIN { print (o1 >= t1)?"1":"0" }' < soma.txt)
if [[ $var -eq 1 ]]
then
> soma.txt
else
:
fi
done
fi
done 3<resultado.txt 5>soma.txt 6>partidasdobradas.txt
resultado.txt
TEST| 31|02/05/2015|6.1.1.01.001|2.1.1.01.005||8.100|DIVERSOS|||N||| ||S|CB|||05|||||||31.000|N|N|||0.000|
TEST| 34|03/05/2015|6.1.1.01.002|2.1.1.01.005||6.900|DIVERSOS|||N||| ||S|CB|||05|||||||34.000|N|N|||0.000|
TEST| 36|03/05/2015|6.1.1.01.002|2.1.1.01.005||8.900|DIVERSOS|||N||| ||S|CB|||05|||||||36.000|N|N|||0.000|
TEST| 38|04/05/2015|6.1.1.01.001|2.1.1.01.005||13.490|DIVERSOS|||N||| ||S|CB|||05|||||||38.000|N|N|||0.000|
TEST| 64|12/05/2015|6.1.1.01.001|2.1.1.01.005||6.780|DIVERSOS|||N||| ||S|CB|||05|||||||64.000|N|N|||0.000|
When you write to soma.txt using >&5 inside the loop, it writes to the file at the current position in the file. When you truncate the file with > soma.txt, the current position isn't reset, so future writes go into the middle of the file, with a bunch of nulls at the beginning.
You should truncate the file before the loop, then use 5>>soma.txt as the redirection of the loop, so it will write in append mode. This will make it automatically seek to the current end of the file.
#!/bin/bash
>soma.txt
while read -r line <&3
do
valorbase=8
valor=0
echo "$line"
echo "Valor:"
read -r valor
echo "$valor" >&5
echo "||||||""$valor""|" >&6
valordasoma=$(awk -F"|" '{ sum += $1 } END { print sum }' < soma.txt)
var=$(awk -v o1=$valordasoma -v t1=$valorbase 'BEGIN { print (o1 >= t1)?"1":"0" }' < soma.txt)
if [[ $var -ge 1 ]]
then
echo "Valor da soma > que, ou = ao valor base"
echo "Repete comando para a linha"
else [[ $var -lt 1 ]]
until [[ $var -eq 1 ]]
do
echo "Valor:"
read -r valor
echo "$valor" >&5
echo "||||||""$valor""|" >&6
valordasoma=$(awk -F"|" '{ sum += $1 } END { print sum }' < soma.txt)
var=$(awk -v o1=$valordasoma -v t1=$valorbase 'BEGIN { print (o1 >= t1)?"1":"0" }' < soma.txt)
if [[ $var -eq 1 ]]
then
> soma.txt
else
:
fi
done
fi
done 3<resultado.txt 5>>soma.txt 6>partidasdobradas.txt

Best way to merge two lines with same pattern

I have a text file like below
Input:
05-29-2015,03:15:00,SESM1_0,ABC,interSesm,REDIRECTED_CALLS,0
05-29-2015,03:15:00,SESM1_0,ABC,interSesm,CALLS_TREATED,0
I am wondering the best way to merge two lines into:
05-29-2015,03:15:00,SESM1_0,ABC,interSesm,REDIRECTED_CALLS,0,CALLS_TREATED,0
With this as the input file:
$ cat file
05-29-2015,03:15:00,SESM1_0,ABC,interSesm,REDIRECTED_CALLS,0
05-29-2015,03:15:00,SESM1_0,ABC,interSesm,CALLS_TREATED,0
We can get the output you want with:
$ awk -F, -v OFS=, 'NR==1{first=$0;next;} {print first,$6,$7;}' file
05-29-2015,03:15:00,SESM1_0,ABC,interSesm,REDIRECTED_CALLS,0,CALLS_TREATED,0
This is a more general solution that reads both files, item by item, where items are separated by comma. After the first mismatch, remaining items from the first line are appended to the output, followed by remaining items from the second line.
The most complicated tool this uses is sed. Looking at it again, even sed can be replaced.
#!/bin/bash
inFile="$1"
tmp=$(mktemp -d)
sed -n '1p' <"$inFile" | tr "," "\n" > "$tmp/in1"
sed -n '2p' <"$inFile" | tr "," "\n" > "$tmp/in2"
{ while true; do
read -r f1 <&3; r1=$?
read -r f2 <&4; r2=$?
[ $r1 -ne 0 ] || [ $r2 -ne 0 ] && break
[ $r1 -ne 0 ] && echo "$f2"
[ $r2 -ne 0 ] && echo "$f1"
if [ "$f1" == "$f2" ]; then
echo "$f1"
else
while echo "$f1"; do
read -r f1 <&3 || break
done
while echo "$f2"; do
read -r f2 <&4 || break
done
fi
done; } 3<"$tmp/in1" 4<"$tmp/in2" | tr '\n' ',' | sed 's/.$/\n/'
rm -rf "$tmp"
Assuming your input file looks like this:
$ cat in.txt
05-29-2015,03:15:00,SESM1_0,ABC,interSesm,REDIRECTED_CALLS,0
05-29-2015,03:15:00,SESM1_0,ABC,interSesm,CALLS_TREATED,0
You can then run the script as:
$ ./merge.sh in.txt
05-29-2015,03:15:00,SESM1_0,ABC,interSesm,REDIRECTED_CALLS,0,CALLS_TREATED,0

bash, adding string after a line

I'm trying to put together a bash script that will search a bunch of files and if it finds a particular string in a file, it will add a new line on the line after that string and then move on to the next file.
#! /bin/bash
echo "Creating variables"
SEARCHDIR=testfile
LINENUM=1
find $SEARCHDIR* -type f -name *.xml | while read i; do
echo "Checking $i"
ISBE=`cat $i | grep STRING_TO_SEARCH_FOR`
if [[ $ISBE =~ "STRING_TO_SEARCH_FOR" ]] ; then
echo "found $i"
cat $i | while read LINE; do
((LINENUM=LINENUM+1))
if [[ $LINE == "<STRING_TO_SEARCH_FOR>" ]] ; then
echo "editing $i"
awk -v "n=$LINENUM" -v "s=new line to insert" '(NR==n) { print s } 1' $i
fi
done
fi
LINENUM=1
done
the bit I'm having trouble with is
awk -v "n=$LINENUM" -v "s=new line to insert" '(NR==n) { print s } 1' $i
if I just use $i at the end, it will output the content to the screen, if I use $i > $i then it will just erase the file and if I use $i >> $i it will get stuck in a loop until the disk fills up.
any suggestions?
Unfortunately awk dosen't have an in-place replacement option, similar to sed's -i, so you can create a temp file and then remove it:
awk '{commands}' file > tmpfile && mv tmpfile file
or if you have GNU awk 4.1.0 or newer, the -i inplace is added, so you can do:
awk -i inplace '{commands}' file
to modify the original
#cat $i | while read LINE; do
# ((LINENUM=LINENUM+1))
# if [[ $LINE == "<STRING_TO_SEARCH_FOR>" ]] ; then
# echo "editing $i"
# awk -v "n=$LINENUM" -v "s=new line to insert" '(NR==n) { print s } 1' $i
# fi
# done
# replaced by
sed -i 's/STRING_TO_SEARCH_FOR/&\n/g' ${i}
or use awk in place of sed
also
# ISBE=`cat $i | grep STRING_TO_SEARCH_FOR`
# if [[ $ISBE =~ "STRING_TO_SEARCH_FOR" ]] ; then
#by
if [ $( grep -c 'STRING_TO_SEARCH_FOR' ${i} ) -gt 0 ]; then
# if file are huge, if not directly used sed on it, it will be faster (but no echo about finding the file)
If you can, maybe use a temporary file?
~$ awk ... $i > tmpfile
~$ mv tmpfile $i
Or simply awk ... $i > tmpfile && mv tmpfile $i
Note that, you can use mktemp to create this temporary file.
Otherwise, with sed you can insert a line right after a match:
~$ cat f
auie
nrst
abcd
efgh
1234
~$ sed '/abcd/{a\
new_line
}' f
auie
nrst
abcd
new_line
efgh
1234
The command search if the line matches /abcd/, if so, it will append (a\) the line new_line.
And since sed as the -i to replace inline, you can do:
if [[ $ISBE =~ "STRING_TO_SEARCH_FOR" ]] ; then
echo "found $i"
echo "editing $i"
sed -i "/STRING_TO_SEARCH_FOR/{a
\new line to insert
}" $i
fi

Using 'if' within a 'while' loop in Bash

I have these diff results saved to a file:
bash-3.00$ cat /tmp/voo
18633a18634
> sashabrokerSTP
18634a18636
> sashatraderSTP
21545a21548
> yheemustr
I just really need the logins:
bash-3.00$ cat /tmp/voo | egrep ">|<"
> sashaSTP
> sasha
> yhee
bash-3.00$
But when I try to iterate through them and just print the names I get errors.
I just do not understand the fundamentals of using "if" with "while loops".
Ultimately, I want to use the while loop because I want to do something to the lines - and apparently while only loads one line into memory at a time, as opposed to the whole file at once.
bash-3.00$ while read line; do if [[ $line =~ "<" ]] ; then echo $line ; fi ; done < /tmp/voo
bash-3.00$
bash-3.00$
bash-3.00$ while read line; do if [[ egrep "<" $line ]] ; then echo $line ; fi ; done < /tmp/voo
bash: conditional binary operator expected
bash: syntax error near `"<"'
bash-3.00$
bash-3.00$ while read line; do if [[ egrep ">|<" $line ]] ; then echo $line ; fi ; done < /tmp/voo
bash: conditional binary operator expected
bash: syntax error near `|<"'
bash-3.00$
There has to be a way to loop through the file and then do something to each line. Like this:
bash-3.00$ while read line; do if [[ $line =~ ">" ]];
then echo $line | tr ">" "+" ;
if [[ $line =~ "<" ]];
then echo $line | tr "<" "-" ;
fi ;
fi ;
done < /tmp/voo
+ sashab
+ sashat
+ yhee
bash-3.00$
You should be checking for >, not <, no?
while read line; do
if [[ $line =~ ">" ]]; then
echo $line
fi
done < /tmp/voo
Do you really need regex here? The following shell glob can also work:
while read line; do [[ "$line" == ">"* ]] && echo "$line"; done < /tmp/voo
OR use AWK:
awk '/^>/ { print "processing: " $0 }' /tmp/voo
grep will do:
$ grep -oP '> \K\w+' <<END
18633a18634
> sashabrokerSTP
18634a18636
> sashatraderSTP
21545a21548
> yheemustr
END
sashabrokerSTP
sashatraderSTP
yheemustr

Resources