Reputation: 113
I am trying to search for a keyword in a file, starting from the nth line onwards. And if its found, set a variable to true For example, file contents of testtext.txt:
abc-0
def-0
xyz-0
abc-1
xxx-1
I want to search keyword 'def' from the 3rd line onwards and if found, print true. Also assuming the nth line is a pass in value.
I have a rough idea below, but not sure how to fix it.
#!/bin/bash
keyword=def
nthline=3
flag=false
count=$(awk 'NR>$nthline' ./testtext.txt | grep '$keyword' | wc -l)
if [[ $count -gt 0 ]];then
flag=true
fi
echo $flag
Expected output should be false, because def doesnt exist on the 3rd line onwards.
Problem is I cannot pass in the 'nthline' variable into the NR> of awk and also cannot pass in $keyword to the grep on that line
I have tested using actual values instead of pass in, it works, so the commands should be working.
count=$(awk 'NR>3' ./testtext.txt | grep 'def' | wc -l)
Is there any way to do this, or any other better solution?
EDIT: Got a solution that is almost 90% there, but I need to assign the variable after the flag is true. this is what I have so far, I am not sure if there is any better way of doing it.
#!/bin/bash
flagz=false
tgt="def"
n=$1
flagz=$(awk -v tgt="$tgt" -v n="$n" flag="$flagz"'
FNR>=n && index($0,tgt){
print("true1")
exit
}
' ./testtext.txt)
echo "$flagz"
Upvotes: 3
Views: 739
Reputation: 4865
Suggesting:
awk 'NR > 3 && /def/{print 1}' testtext.txt
NR > 3
means if the total number of records greater than 3 &&
the query def
in /def
was found, print 1
.
Upvotes: 0
Reputation: 103774
It would be best to do this entirely in awk
since you are already using awk to slice the file.
Example:
tgt="def"
n=3
awk -v tgt="$tgt" -v n="$n" '
BEGIN{flag="false"}
FNR>=n && index($0,tgt){
flag="true"
exit
}
END{print flag}' file
Alternatively, you can make a pipe and then inspect $?
to see if grep
found your match:
tgt="def"
n=2
tail -n "+$n" file | grep "$tgt" >/dev/null
Now $?
will be 0
if the grep finds the pattern and 1
if it is not found. Then you can set a flag like so:
flag="false"
tail -n "+$n" file | grep "$tgt" >/dev/null
[ $? ] && flag="true"
Now flag
is set true / false based on the grep. The command tail -n +[some number] file
will print the file contents from the absolute line number onward.
For large files, the awk is significantly more efficient since it exits on the first match.
Edit based on update.
The issue is setting a Bash flag to true
or false
based on a process.
The $?
Special Parameter is set based on the exit status of the most recently executed foreground pipeline. So pick your method to slice the file and detect the string and then set the flag in your script based on $?
immediately after the pipe. Be aware that testing $?
resets $?
before it is tested -- so you either need to capture the value of $?
before the test or use it in the pipeline itself.
These methods work:
1) Capture $? and test:
awk -v tgt="$tgt" -v n="$n" -v flag=1 '
FNR>=n && index($0,tgt){
flag=0
exit
}
END{ exit flag }
' ./testtext.txt
res=$?
[ $res -eq 1 ] && flagz=false || flagz=true
2) Capture a string result and test that:
res=$(awk -v tgt="$tgt" -v n="$n" -v flag="false" '
FNR>=n && index($0,tgt) {
flag="true"
exit
}
END{ print flag }' ./testtext.txt)
[ $res = "false" ] && flagz=false || flagz=true
3) Use a pipe and test in the pipe:
tail -n "+$n" file | grep "$tgt" >/dev/null && flagz=true || flagz=false
My preference is 3 for small files and 2 for big files.
Upvotes: 3
Reputation: 84551
Another way to do this is with sed
and a range expression telling sed
to search from line 3 to end 3,$
. The types of expressions that accept addr1,addr2
is limited but does include the traditional substitute form of sed 's/find/replace/
. Where you can search for the entire line containing def
and then replace it with &
(shorthand for the entire matched expression).
To control printing pass the -n
option (suppress normal printing of pattern space) and add p
(print) at the end of the substitute expression, e.g.
sed -n '3,$ s/^.*def.*$/&/p' file
The above skips the first two lines and begins the search/replacement on line 3.
Upvotes: 1
Reputation: 8064
Try:
tail -n "+$nthline" testtext.txt | grep -qF -- "$keyword" && flag=true || flag=false
Upvotes: 0