i am trying to write a code where i have used an IF statement.
here I am trying to compare 2 string that are obtained by using an awk statement.
Please help me...if this is possible.
if [ "awk '/$search/ {print $3}' rpt1.txt" -eq "awk '/$search/ {print $3}' rpt2.txt" ]
Sure, using $() or ``.
if [ $(awk '/$search/ {print $3}' rpt1.txt) -eq $(awk '/$search/ {print $3}' rpt2.txt) ]
If you want string comparison rather than numeric you probably want = instead of -eq though.
Might read better if you made a function too:
search_report() {
awk "/$1/ { print \$3 }" $2
}
if [ $(search_report $search rpt1.txt) -eq $(search_report $search rpt2.txt) ]
...
You can capture stdout into a variable like this:
variable=$(command)
Try this
rpt1=$(awk '/$search/ {print $3}' rpt1.txt)
rpt2=$(awk '/$search/ {print $3}' rpt2.txt)
if [ "${rpt1}" == "${rpt2}" ]; then
echo "match";
fi
The operator -eq works with integers only, that's why I used == instead.
More about capturing stdout
http://www.cyberciti.biz/faq/unix-linux-bsd-appleosx-bash-assign-variable-command-output/
This is a excellent summary of operators in bash
http://tldp.org/LDP/abs/html/comparison-ops.html
Related
How do I select the first column from the TAB separated string?
# echo "LOAD_SETTLED LOAD_INIT 2011-01-13 03:50:01" | awk -F'\t' '{print $1}'
The above will return the entire line and not just "LOAD_SETTLED" as expected.
Update:
I need to change the third column in the tab separated values.
The following does not work.
echo $line | awk 'BEGIN { -v var="$mycol_new" FS = "[ \t]+" } ; { print $1 $2 var $4 $5 $6 $7 $8 $9 }' >> /pdump/temp.txt
This however works as expected if the separator is comma instead of tab.
echo $line | awk -v var="$mycol_new" -F'\t' '{print $1 "," $2 "," var "," $4 "," $5 "," $6 "," $7 "," $8 "," $9 "}' >> /pdump/temp.txt
You need to set the OFS variable (output field separator) to be a tab:
echo "$line" |
awk -v var="$mycol_new" -F'\t' 'BEGIN {OFS = FS} {$3 = var; print}'
(make sure you quote the $line variable in the echo statement)
Make sure they're really tabs! In bash, you can insert a tab using C-v TAB
$ echo "LOAD_SETTLED LOAD_INIT 2011-01-13 03:50:01" | awk -F$'\t' '{print $1}'
LOAD_SETTLED
Use:
awk -v FS='\t' -v OFS='\t' ...
Example from one of my scripts.
I use the FS and OFS variables to manipulate BIND zone files, which are tab delimited:
awk -v FS='\t' -v OFS='\t' \
-v record_type=$record_type \
-v hostname=$hostname \
-v ip_address=$ip_address '
$1==hostname && $3==record_type {$4=ip_address}
{print}
' $zone_file > $temp
This is a clean and easy to read way to do this.
You can set the Field Separator:
... | awk 'BEGIN {FS="\t"}; {print $1}'
Excellent read:
https://docs.freebsd.org/info/gawk/gawk.info.Field_Separators.html
echo "LOAD_SETTLED LOAD_INIT 2011-01-13 03:50:01" | awk -v var="test" 'BEGIN { FS = "[ \t]+" } ; { print $1 "\t" var "\t" $3 }'
If your fields are separated by tabs - this works for me in Linux.
awk -F'\t' '{print $1}' < tab_delimited_file.txt
I use this to process data generated by mysql, which generates tab-separated output in batch mode.
From awk man page:
-F fs
--field-separator fs
Use fs for the input field separator (the value of the FS prede‐
fined variable).
1st column only
— awk NF=1 FS='\t'
LOAD_SETTLED
First 3 columns
— awk NF=3 FS='\t' OFS='\t'
LOAD_SETTLED LOAD_INIT 2011-01-13
Except first 2 columns
— {g,n}awk NF=NF OFS= FS='^([^\t]+\t){2}'
— {m}awk NF=NF OFS= FS='^[^\t]+\t[^\t]+\t'
2011-01-13 03:50:01
Last column only
— awk '($!NF=$NF)^_' FS='\t', or
— awk NF=NF OFS= FS='^.*\t'
03:50:01
Should this not work?
echo "LOAD_SETTLED LOAD_INIT 2011-01-13 03:50:01" | awk '{print $1}'
If I have a string:
s='path/to/my/foo.txt'
and an array
declare -a include_files=('foo.txt' 'bar.txt');
how can I check the string for matches in my array efficiently?
You could loop through the array and use a bash substring check
for file in "${include_files[#]}"
do
if [[ $s = *${file} ]]; then
printf "%s\n" "$file"
fi
done
Alternately, if you want to avoid the loop and you only care that a file name matches or not, you could use the # form of bash extended globbing. The following example assumes that array file names do not contain |.
shopt -s extglob
declare -a include_files=('foo.txt' 'bar.txt');
s='path/to/my/foo.txt'
printf -v pat "%s|" "${include_files[#]}"
pat="${pat%|}"
printf "%s\n" "${pat}"
#prints foo.txt|bar.txt
if [[ ${s##*/} = #(${pat}) ]]; then echo yes; fi
For an exact match to the file name:
#!/bin/bash
s="path/to/my/foo.txt";
ARR=('foo.txt' 'bar.txt');
for str in "${ARR[#]}";
do
# if [ $(echo "$s" | awk -F"/" '{print $NF}') == "$str" ]; then
if [ $(basename "$s") == "$str" ]; then # A better option than awk for sure...
echo "match";
else
echo "no match";
fi;
done
I need to pass a specific value from shell to a AWK script file but i dont know i cant do it.
#! /bin/bash
if [ "$2" = "-C" ] && [ "$3" != "" ]; then
awk -f SpecCity.awk $1
elif [ "$2" = "-C" ] && [ "$3" = "" ]; then
awk -f CityOnly.awk $1
fi
I need to pass the value $3 to AWK which will compare it with the a file i will point but i cant do it.
Any idea how to do it ?
Thankyou
You should be able to use "awk -v". For example, "awk -v city=$3..."
Newer versions of awk should also support the "ENVIRON[]" array.
Both options are discussed here:
http://unix-school.blogspot.com/2011/09/awk-passing-arguments-or-shell.html
i've got a bash variable that contains an IP address (no CIDR or anything, just the four octets).
i need to break that variable into four separate octets like this:
$ip = 1.2.3.4;
$ip1 = 1
$ip2 = 2
# etc
so i can escape the period in sed. is there a better way to do this? is awk what i'm looking for?
You could use bash. Here's a one-liner that assumes your address is in $ip:
IFS=. read ip1 ip2 ip3 ip4 <<< "$ip"
It works by setting the "internal field separator" for one command only, changing it from the usual white space delimiter to a period. The read command will honor it.
If you want to assign each octet to its own variable without using an array or a single variable with newline breaks (so you can easily run it through a for loop), you could use # and % modifiers to ${x} like so:
[ 20:08 jon#MacBookPro ~ ]$ x=192.160.1.1 && echo $x
192.160.1.1
[ 20:08 jon#MacBookPro ~ ]$ oc1=${x%%.*} && echo $o1
192
[ 20:08 jon#MacBookPro ~ ]$ x=${x#*.*} && echo $x
160.1.1
[ 20:08 jon#MacBookPro ~ ]$ oc2={x%%.*} && echo $o2
160
[ 20:08 jon#MacBookPro ~ ]$ x=${x#*.*} && echo $x
1.1
[ 20:08 jon#MacBookPro ~ ]$ oc3=${x%%.*} && echo $o3
1
[ 20:08 jon#MacBookPro ~ ]$ x=${x#*.*} && echo $x
1
[ 20:08 jon#MacBookPro ~ ]$ oc4=${x%%.*} && echo $oc4
1
[ 20:09 jon#MacBookPro ~ ]$ echo "$oc1\.$oc2\.$oc3\.$oc4"
192\.160\.1\.1
See this /wiki/Bash:_Append_to_array_using_while-loop
and more in this article.
You can split strings using the set built-in, with IFS as separator (normally space and tab).
splitip () {
local IFS
IFS=.
set -- $*
echo "$#"
}
splitip 12.34.56.78
# Now $1 contains 12, $2 contains 34, etc
If you just need to backslash-escape the dots, use string substitution - bash has ${ip//./\\.}
This code is something that I found on another site when I was looking to do the same thing. Works perfectly for my application.
read ICINGAIPADDRESS
# The following lines will break the ICINGAIPADDRESS variable into the four octets
# and assign each octet to a variable.
ipoct1=$(echo ${ICINGAIPADDRESS} | tr "." " " | awk '{ print $1 }')
ipoct2=$(echo ${ICINGAIPADDRESS} | tr "." " " | awk '{ print $2 }')
ipoct3=$(echo ${ICINGAIPADDRESS} | tr "." " " | awk '{ print $3 }')
ipoct4=$(echo ${ICINGAIPADDRESS} | tr "." " " | awk '{ print $4 }')
The easier way is using AWK:
echo 192.168.0.12 | awk -F. '{print $1 $2 $3 $4}'
-F is a field separator, in this case we use the dot "." as separator and print each column individually.
mortiz#florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $1 $2 $3 $4}'
76220156100
mortiz#florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $1}'
76
mortiz#florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $2}'
220
mortiz#florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $3}'
156
mortiz#florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $4}'
100
Let's say i have file like this
adsf(2)
af(3)
g5a(65)
aafg(1245)
a(3)df
How can i get from this only numbers between ( and ) ?
using BASH
A couple of solution comes to mind. Some of them handles the empty lines correctly, others not. Trivial to remove those though, using either grep -v '^$' or sed '/^$/d'.
sed
sed 's|.*(\([0-9]\+\).*|\1|' input
awk
awk -F'[()]' '/./{print $2}' input
2
3
65
1245
3
pure bash
#!/bin/bash
IFS="()"
while read a b; do
if [ -z $b ]; then
continue
fi
echo $b
done < input
and finally, using tr
cat input | tr -d '[a-z()]'
while read line; do
if [ -z "$line" ]; then
continue
fi
line=${line#*(}
line=${line%)*}
echo $line
done < file
Positive lookaround:
$ echo $'a1b(2)c\nd3e(456)fg7' | grep -Poe '(?<=\()[0-9]*(?=\))'
2
456
Another one:
while read line ; do
[[ $line =~ .*\(([[:digit:]]+)\).* ]] && echo "${BASH_REMATCH[1]}"
done < file