I have been trying for hours on a certain parts of my program, I will be greatful if someone can help me. I still cannot solve the problem of adding a new line called "Book is not found" at the bottom when 0 record is found, how do i do that? How do i make the search to be case insensitive also?
awk -F':' -v search="$title" '{ if($1 == search) {printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5; i++ } else {printf "Book not found"} }END {printf "%d records found\n", i}' BookDB.txt
This give me things like
Title:dwaf
Author:
Book not found
Book not found
Book not found
Total, 0 record found
instead of
Title:wdawd
Author:
Book not found
Total, 0 record found
If a record exist, it will show
Book not found
Book not found
Book not found
Book not found
Happy Day book
Happy Day book
Happy Day book
Book not found
3 records found
instead of
Happy Day book
Happy Day book
Happy Day book
3 records found
This does not show the "book not found" message
if [ "$title" != "" ] && [ "$author" = "" ] ; then
awk -F':' -v search="$title" '{ if($1 == search) {printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5; i++ } else {printf "Book not found"} }END {printf "%d records found\n", i}' BookDB.txt
if [ "$i" < 1 ]; then
echo -n "Book not found"
fi
Next i have a error of case insensitive
i try to change the code
awk -F':' -v search="$title" 'IGNORECASE = 1;/^search/;'
BEGIN { i=0; }
{
if($1 == search) {
printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5
i++
}
}
END {
if(i >= 1) {
printf "%d records found\n", i
} else {
printf "Book not found\n"
}
}' BookDB.txt
i isn't a shell variable; it's only an awk variable. Thus, you can only reference it inside of awk code (and in the same instance of awk in which it was set).
Consider the following:
awk -F':' -v search="$title" '
BEGIN { i=0; }
{
if($1 == search) {
printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5
i++
}
}
END {
if(i >= 1) {
printf "%d records found\n", i
} else {
printf "Book not found\n"
}
}' BookDB.txt
Now, if you wanted to do this in bash, instead of awk, I might write it like so:
#!/bin/bash
# ^-- must be /bin/bash, not /bin/sh
title=$1 # or get it from somewhere else, but needs to be assigned
i=0
while IFS=: read -r -a fields; do
if [[ ${fields[0]} = "$title" ]]; then
IFS=,; printf '%s\n' "${fields[*]}"
i=$(( i + 1 ))
fi
done <BookDB.txt
if (( i > 0 )); then
echo "$i books found" >&2
else
echo "Book not found" >&2
fi
For case-insensitivity, I'd change the bash version like so:
title=${1,,} # store title in lower-case
# ...and lower-case the first field when comparing it.
if [[ ${fields[0],,} = "$title" ]]; then
Related
I'm trying to check filed on log file , line by line. For each line, check if specific filed is empty or field have wrong value .
And print line with the error message
#!/bin/bash
LOG=/log/output.log
x=false
while read -r line; do
if
(echo $line | awk -F'|' '{if ($8=="") print "Application is empty"}') ||
(echo $line | awk -F'|' '{if ($9=="") print "Http request method is empty"}') ||
(echo $line | awk -F'|' '{if ($7=="") print "Operation is empty"}')
(echo $line | awk -F'|' '{if ($13 !~ /0|1|2/) print "result(0,1,2) has a wrong value"}')
then
echo $line
fi
done < "$LOG"
Actual results:
9f2b|EDR|V1|0|V1|2019-05-14|7||||2019-05-14T08:00:40.095Z|1|0|14|19|||XXXXX|||||||||897|||||||||5b8689707|||||||
Application is empty
9f2b|EDR|V1|0|V1|2019-05-14|7||||2019-05-14T08:00:40.095Z|18|0|||||XXXXX|||||||||1234|||||||||5b868007|||||||
Application is empty
42e2|EDR|V1|0|V1|2019-05-14|7||||2019-05-14T08:00:42.532Z|22|0|||||XXXXX|||||||||235|||||||||3b6959ae||||||||
Application is empty
83ac|EDR|V1|0|V1|2019-05-14|7||||2019-05-14T08:00:42.758Z|8|0|||||XXXXX|||||||||789|||||||||5945548f|||||
Expected Result:
Application is empty
Operation is empty
Http request method is empty
83ac|EDR|V1|0|V1|2019-05-14|7||||2019-05-14T08:00:42.758Z|8|0|||||XXXXX|||||||||789|||||||||5945548f|||||
awk reads every line of the file, so there's no need for your while loop with echos. Just do:
awk -F\| ' {b=1}
$8=="" { print "Application is empty"; b=0 }
$9=="" { print "Http request method is empty"; b=0 }
$7=="" { print "Operation is empty"; b=0 }
$13 !~ /0|1|2/ {print "result(0,1,2) has a wrong value"; b=0 }
b
' /log/output.log
The main problem with your approach is that the command you are evaluating with if always succeeds, so you always print the line. To make awk fail, you would have to add exit statements to each of the awk statements. (eg echo $line | awk -F'|' '$8=="" {print "Application is empty"; exit 1 }'
This will print multiple error messages if a line fails multiple conditions, which yours will not do if you add the exit statements and short circuit the || operators.
If you want to print only one error message, you could do:
awk -F\| '
$8=="" { print "Application is empty"; next }
$9=="" { print "Http request method is empty"; next }
$7=="" { print "Operation is empty"; next }
$13 !~ /0|1|2/ {print "result(0,1,2) has a wrong value"; next }
' /log/output.log
Or, if you want to print multiple error messages, but all on one line, you could do:
awk -F\| ' {s=""}
$8=="" { printf "Application is empty"; s="; " }
$9=="" { printf "%sHttp request method is empty", s; s="; " }
$7=="" { printf "%sOperation is empty", s; s="; " }
$13 !~ /0|1|2/ {printf "%sresult(0,1,2) has a wrong value", s; s="; " }
s { print ""}
!s
' /log/output.log
I am using awk function for pattern matching. If awk contains operator sign such as ++ or -- it will give me error for searching.
For example during searching
4) search_book
Title: C++ Programming in 21 Days
Author:
0 records found
however without the C++(actually without the ++, cause if i type C, i will still get the result)
4) search_book
Title: Programming in 21 Days
Author:
C++ Programming in 21 Days, Hacker Jane,$30.60,18,10
C++ Programming in 21 Days, J. D. Edwards,$50.03,15,10
C++ Programming in 21 Days, Paul Thompson,$45.00,18,10
3 records found
This is awk coding
awk -F':' -v search="$title" '$1 ~ search { i++; printf "%s, %s,$%s,%s,%s\n", $1, $2, $3, $4, $5 } END { printf "%d records found\n", i }' BookDB.txt
Update:
I have been trying for hours, but i still cannot solve the problem,if i want to add a new line called "Book is not found" at the bottom when 0 record is found, how do i do that?
How do i make it to be case insensitive also?
awk -F':' -v search="$title" '{ if($1 == search) {printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5; i++ } else {printf "Book not found"} }END {printf "%d records found\n", i}' BookDB.txt
This give me things like
Book not found
Book not found
c++ programming in 21 days
Book not found
This does not show the "book not found" message
if [ "$title" != "" ] && [ "$author" = "" ] ; then
awk -F':' -v search="$title" '{ if($1 == search) {printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5; i++ } else {printf "Book not found"} }END {printf "%d records found\n", i}' BookDB.txt
if [ "$i" < 1 ]; then
echo -n "Book not found"
fi
$1 ~ search treats the variable search as a regular expression. If you don't want that, you can use the index function which searches for literal strings, not regexes:
$ title='C++ Programming in 21 Days'
$ awk -F: -v search="$title" '(index($1, search) != 0) { i++; printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5 } END { printf "%d records found\n", i }' BookDB.txt
C++ Programming in 21 Days, Hacker Jane,$30.60,18,10
C++ Programming in 21 Days, J. D. Edwards,$50.03,15,10
C++ Programming in 21 Days, Paul Thompson,$45.00,18,10
3 records found
index($1, search) returns the location of the string search inside the string $1. If search is not found, then index returns 0.
I changed -F':' to -F:. This works because : is not a shell-active character. There is no harm in quoting it but the quotes are not necessary.
Updated Question
To get book not found:
$ awk -F: -v search="$title" '(index($1, search) != 0) { i++; printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5 } END { if (i) printf "%d records found\n", i ; else print "Book not found";}' BookDB.txt
If you have GNU awk (gawk), then adding case-insensitivity is easy:
awk -F: -v search="$title" 'BEGIN{IGNORECASE=1;} (index($1, search) != 0) { i++; printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5 } END { if (i) printf "%d records found\n", i ; else print "Book not found";}' BookDB.txt
If it makes it easier to understand, here is the same code spread over multiple lines:
awk -F: -v search="$title" '
BEGIN{
IGNORECASE=1;
}
(index($1, search) != 0){
i++;
printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5
}
END{
if (i)
printf "%d records found\n", i ;
else
print "Book not found";
}
' BookDB.txt
i have written awk to print specyfic lines from space-delimited log file.
if [ ! -f $userlog ]
then
awk -F' ' '$7$8 == "Loginitialized" {print $2" "$3" "$4" "$5" process start"}''$7$8$9 == "Applictionsuccessfullyended" {print $2" "$3" "$4" "$5" process end"}' $preplog > $userlog
fi
output sample (userlog)
2015-03-02 13:14:25 (PID 19594) process start
2015-03-02 22:42:29 (PID 30473) process start
2015-03-02 22:53:20 (PID 30473) process end
2015-03-03 07:16:55 (PID 31078) process start
2015-03-03 14:53:15 (PID 16591) process start
2015-03-03 14:54:10 (PID 18292) process start
I need to use same awk on $preplog but from last line i've printed with it.
i was trying with that but i failed:
if [ -f $userlog ]
then
lastpid=`awk -F' ' 'END{print $4}' $userlog` #pid ostatniego procesu
cat $preplog | awk 'BEGIN{ found=0} /PID /$lastpid/ Log initialized/{found=1} {if (found) {awk -F" " "$7$8 == "Loginitialized" {print $2" "$3" "$4" "$5" process start"}''$7$8$9 == "Applictionsuccessfullyended" {print $2" "$3" "$4" "$5" process end"}"} ;}' >> $userlog
fi
but my awk programing is not strong in me. I literaly have no idea how to bite it.
Let's start by cleaning up you current script:
awk -F' ' '$7$8 == "Loginitialized" {print $2" "$3" "$4" "$5" process start"}''$7$8$9 == "Applictionsuccessfullyended" {print $2" "$3" "$4" "$5" process end"}' $preplog > $userlog
Change that to:
awk '
$7$8 == "Loginitialized" { state="start" }
$7$8$9 == "Applictionsuccessfullyended" { state="end" }
state { print $2, $3, $4, $5, "process", state; state="" }
' "$preplog" > "$userlog"
for improved robustness and clarity, and to remove unnecessary constructs and redundancy.
For what you want to do next though - see if reading https://stackoverflow.com/a/18409469/1745001 helps and if not edit your question to show sample input and expected output plus a clearer, more detailed explanation of what you're trying to do.
Hang on, I think I just had a revelation after re-reading your attempted code segment - MAYBE what you want is to only analyze and operate on the last line of the input file instead of every line of it. If so that'd be:
awk '
{ var1=$7$8; var2=$7$8$9 }
END {
if (var1 == "Loginitialized") { state="start" }
if (var2 == "Applictionsuccessfullyended") { state="end" }
if (state) { print $2, $3, $4, $5, "process", state; state="" }
}
' "$preplog" > "$userlog"
If that's not what you wanted you'll need to provide more information.
I have a problem of being unable to printout a error message if 0 records are found.
this is what I have as of now.
function search_title
{
awk -F':' -v search="$Title" '$2 ~ search { i++;} END { printf "%d records found\n", i }' test.txt
awk -F':' -v search="$Title" '$2 ~ search { i++; printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5 } END {}' test.txt
}
function search_author
{
awk -F':' -v search="$Author" '$2 ~ search { i++;} END { printf "%d records found\n", i }' test.txt
awk -F':' -v search="$Author" '$2 ~ search { i++; printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5 } END {}' test.txt
}
function search_both
{
awk -F':' -v search="$Title" -v search1="$Author" '$1 ~ search && $2 ~ search1 { i++;} END { printf "%d records found\n", i }' test.txt
awk -F':' -v search="$Title" -v search1="$Author" '$1 ~ search && $2 ~ search1 { i++; printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5 } END {}' test.txt
}
read -p $'Title: ' Title
read -p $'Author: ' Author
if [ "$Title" == "" ];
then
search_author
elif [ "$Author" == "" ];
then
search_title
else
search_both
fi
I need a if else statement to check if the counter is 0 in awk print out "Error! Book does not exist"
For example,
Title input as DAFT
Author input as Linken
(Both value not in test.txt)
"Error! Book does not exist"
instead of the printf now which is "0 Record Found"
You don't need 2 awk command in each function:
You can combine both awk in one command:
awk -F':' -v search="$Title" -v search1="$Author" '$1 ~ search && $2 ~ search1 {
i++;
printf "%s, %s,%s,%s,%s\n", $1, $2, $3, $4, $5;
}
END {
if (!i)
print "Error! Book does not exists!";
else
printf "%d records found\n", i;
}' test.txt
I want to monitor Disk IO of a server and want to set different threshold for
the warning if %busy above 60% and
error if %busy above 80%.
From sar output need to find error disk with more than 80% busy and on 2nd line need disk more than 60 but less than 80% busy if disk not crossing theresholds then it should print 'ok' for respective category
I've created a script which will do this, but is there a better way to run sar just one time and use the same output for error & warning threshold? My system is AIX 6.1.
sar -d 2 2 |sed -n '/Average/,$p'|
sed -e 's/Average//g'|
awk 'NR> 1 {
if ($2 >80) {
print $1, $2; f=1
}
}
END { if (!f) print "ok" }'
sar -d 2 2 |
sed -n '/Average/,$p'|
sed -e 's/Average//g'|
awk 'NR> 1{ if ($2 >60 && $2 <81) { print $1, $2; f=1; } }
END { if (!f) print "ok" }'
Pls find my updated script below
bash-3.00$ cat diskio.sh
#!/bin/bash
a=`sar -d 2 2 |sed -n '/Average/,$ {s/Average//g;p;}'`
e=`$a|awk 'NR> 1{ if ($2 >40) { print $1, $2; f=1; } }
END { if (!f) print "ok" }'`
w=`$a|awk 'NR> 1{ if ($2 <40 && $2 >20) { print $1, $2; f=1; } }
END { if (!f) print "ok" }'`
echo $e
echo $w
bash-3.00$ sh -v diskio.sh
#!/bin/bash
a=`sar -d 2 2 |sed -n '/Average/,$ {s/Average//g;p;}'`
e=`$a|awk 'NR> 1{ if ($2 >40) { print $1, $2; f=1; } }
END { if (!f) print "ok" }'`
diskio.sh[3]: hdisk18: not found.
w=`$a|awk 'NR> 1{ if ($2 <40 && $2 >20) { print $1, $2; f=1; } }
END { if (!f) print "ok" }'`
diskio.sh[4]: hdisk18: not found.
echo $e
ok
echo $w
ok
bash-3.00$ sar -d 2 2 |
sed -n '/Average/,$ {s/Average//g;p;}'|
awk 'NR> 1{ if ($2 >40) { print $1, $2; f=1; } }
END { if (!f) print "ok" }'
hdisk79 135
hdisk101 85
bash-3.00$
sed -n '/Average/,$p'|sed -e 's/Average//g'
could be replaced by
sed -n '/Average/,$ {s/Average//g;p;}'
but sed does not make any evaluation of value (compare) easily so the awk for all is a better solution
This can be shorten some.
sar -d 2 2 | awk '/Average/ {t=1;next} t && NR>1 && $2>80 {print $1,$2;f=1} END { if (!f) print "ok" }'
This should do what you want
sar -d 2 2 | awk '/Average/ {t=1;next} t && NR>1 {if ($2>80) h=1;if ($2>60) l=1} END {if (h) {print "80+";exit};if (l) print "60+"}'
It will print 60+ if its above 60 and 80+ above 80
Or store it to a variable
status=$(sar -d 2 2 | awk '/Average/ {t=1;next} t && NR>1 {if ($2>80) h=1;if ($2>60) l=1} END {if (h) {print "H";exit};if (l) print "L"}')
Here it set status to L for 60+ and H for 80+
This should also print the status:
sar -d 2 2 | awk '/Average/ {t=1;next} t && NR>1 {if ($2>80) h=1;if ($2>60) {print $1,$2;l=1}} END {if (!l) print "ok"}'