Bash script : read text files using “AND” conditions with different lines

Clash Royale CLAN TAG#URR8PPP
up vote
0
down vote
favorite
I have created simple bash script with "AND" condition but not working :
#!/bin/bash
cat log3.txt |
while read -r LINE
do
if [[ $LINE =~ Host ]] && [[ $LINE =~ denied ]] ; then echo $LINE;
fi
done
and here are content of log3.txt
Host: abcd.com
Access denied
If using OR condition it is working well, but I want to use the AND condition, so if the log contains both of the strings "Host" and "Access Denied", I will get output.
shell-script
add a comment |
up vote
0
down vote
favorite
I have created simple bash script with "AND" condition but not working :
#!/bin/bash
cat log3.txt |
while read -r LINE
do
if [[ $LINE =~ Host ]] && [[ $LINE =~ denied ]] ; then echo $LINE;
fi
done
and here are content of log3.txt
Host: abcd.com
Access denied
If using OR condition it is working well, but I want to use the AND condition, so if the log contains both of the strings "Host" and "Access Denied", I will get output.
shell-script
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have created simple bash script with "AND" condition but not working :
#!/bin/bash
cat log3.txt |
while read -r LINE
do
if [[ $LINE =~ Host ]] && [[ $LINE =~ denied ]] ; then echo $LINE;
fi
done
and here are content of log3.txt
Host: abcd.com
Access denied
If using OR condition it is working well, but I want to use the AND condition, so if the log contains both of the strings "Host" and "Access Denied", I will get output.
shell-script
I have created simple bash script with "AND" condition but not working :
#!/bin/bash
cat log3.txt |
while read -r LINE
do
if [[ $LINE =~ Host ]] && [[ $LINE =~ denied ]] ; then echo $LINE;
fi
done
and here are content of log3.txt
Host: abcd.com
Access denied
If using OR condition it is working well, but I want to use the AND condition, so if the log contains both of the strings "Host" and "Access Denied", I will get output.
shell-script
shell-script
edited Dec 3 at 8:17
Rui F Ribeiro
38.5k1479128
38.5k1479128
asked Dec 3 at 6:47
Widi Anto
32
32
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
up vote
0
down vote
accepted
If you are sure that the files to process are small (like your example), you can read the whole file in one go and test that:
file=$(<log3.txt)
[[ $file =~ Host ]] && [[ $file =~ denied ]] && echo "$file"
For a larger file, and assuming that Host comes before denied you may use a faster (for external files) sed:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;q;b1'
Understand that this solution will strictly print the first line that starts with Host and the following (not in the same line) first line that contains denied as a word.
If you need to extract several pairs of Host - denied, change the q to a b, that will re-start the cycle:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;b;b1'
A similar solution with awk that will print the last Host line that is just before a denied line (in pairs):
awk ' p==1 && /<denied>/ d=$0;p=0
/^Host*/ h=$0;p=1
if(p==0&&h!=""&&d!="") print h,RS,d;p=2
' <log3.txt
And the same logic (except that it will match denied anywhere on the line (not as a word)) in the shell:
#!/bin/sh
p=0
while IFS= read -r line; do
if [ "$p" = 1 ]; then
case $line in
*denied*) deniedline=$line; p=0 ;;
esac
fi
case $line in
Host*) hostline=$line; p=1 ;;
esac
if [ "$p" = 0 ] && [ "$hostline" ] && [ "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
p=2
fi
done <log3.txt
2nd solution doesn't quite work, it prints whatever comes before the first "Host" line and hangs on this input:Host: ok.com/Access OK/Host: denied.com/Access denied.
– xenoid
Dec 3 at 16:44
Yes, the first version assumeddeniedfollowedHost(as it is written on the answer). I made it a lot more robust now. Hard for me to think of a way to break it (until someone figure out how, of course :-) ).
– Isaac
Dec 3 at 21:08
yes 2nd solution it is OR condition
– Widi Anto
Dec 4 at 2:54
and the end solution it is work for me, and it is perfect, thanks.
– Widi Anto
Dec 4 at 2:56
add a comment |
up vote
2
down vote
In any single iteration of your while loop, the value $LINE can't be both Host and denied. It's impossible given the data in the file. This is why you get no output.
If you want to see all lines in the file that matches the two words Host or denied, use grep instead:
grep -wF -e 'Host' -e 'Access denied' <log3.txt
The options used here will ensure that we are doing string comparisons rather than regular expression matches (-F) and that we are matching complete words and not substrings (-w). The two query strings are given with -e and we'll get any line containing any of these.
If you want to make a slightly more advanced query, which only shows the lines that contains the two words if they both appear in the file, then you could do it with an awk program instead:
awk '/Host/ hostline=$0 /Access denied/ deniedline=$0
END if ((hostline != "") && (deniedline != ""))
print hostline; print deniedline; ' <log3.txt
Here, if we find a line matching the string Host, we save it, and likewise for the string Access denied. At the end, if both strings contain anything, we print them.
In more or less equivalent shell code:
#!/bin/sh
while IFS= read -r line; do
case $line in
*Host*)
hostline=$line ;;
*"Access denied"*)
deniedline=$line ;;
esac
done <log3.txt
if [ -n "$hostline" ] && [ -n "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
fi
Here I use a case ... esac statement to do the matching on the read data. The patterns used are filename globbing patterns, not regular expressions.
Related:
- Understanding "IFS= read -r line"
- Why is using a shell loop to process text considered bad practice?
awkcode doesn't seem to work, try withHost: denied1.com/Access denied/Host: ok.com/Access OK/Host: random.com. The question is hard to answer since we don't know what the rest of the file looks like.
– xenoid
Dec 3 at 9:37
@xenoid I've made it slightly more robust, but you are correct that the intended behaviour is unclear.
– Kusalananda
Dec 3 at 9:48
@Kusalananda thanks it works for me
– Widi Anto
Dec 3 at 10:12
Notes worth adding: The grep code will print any line with eitherHostorAccess denied, not as pairs. The awk solution will only print the last instance of the pair. The shell solution will matchHostat any position on the line and will only print the lastHostand the lastAccess deniedfound.
– Isaac
Dec 3 at 21:43
@Kusalananda grep -wF -e 'Host' -e 'Access denied' <log3.txt it is OR condtions, so it works for me when using use case ... esac
– Widi Anto
Dec 4 at 2:29
|
show 1 more comment
up vote
0
down vote
See @Kusalananda answer for why your solution doesn't work.
My solution using grep -z:
grep -zEo -e 'Host: (w|.)+s+Access denieds' log.txt
In slo-mo:
-E: use extended regexp-o: print matches only-z: useas line delimiters. Since there are none, the search is done on the whole file, wherenis just a plain character.- e'Host: (w|.)+s+Access denieds': look for:- "
Host:" - A sequence of letter, digits, or dots
- A space-class character (which is going to be
n) - "
Access denied" - A space-class character (which is going to be
n). This one is need to get a linefeed on output
- "
Running on:
Host: denied1.com
Access denied
Host: ok.com
Access OK
Host: random.com
Host: denied2.com
Access denied
More stuff
Yields:
Host: denied1.com
Access denied
Host: denied2.com
Access denied
this is not work for me, there'is no results after running the command
– Widi Anto
Dec 4 at 2:58
What is the input? Works for me with your two-lines data if the last line ends with a linefeed (like all Linux logs do). If you want to the command to work even it if it is missing, just add a?at the end of the regexp:'Host: (w|.)+sAccess denieds?'
– xenoid
Dec 4 at 7:41
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
If you are sure that the files to process are small (like your example), you can read the whole file in one go and test that:
file=$(<log3.txt)
[[ $file =~ Host ]] && [[ $file =~ denied ]] && echo "$file"
For a larger file, and assuming that Host comes before denied you may use a faster (for external files) sed:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;q;b1'
Understand that this solution will strictly print the first line that starts with Host and the following (not in the same line) first line that contains denied as a word.
If you need to extract several pairs of Host - denied, change the q to a b, that will re-start the cycle:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;b;b1'
A similar solution with awk that will print the last Host line that is just before a denied line (in pairs):
awk ' p==1 && /<denied>/ d=$0;p=0
/^Host*/ h=$0;p=1
if(p==0&&h!=""&&d!="") print h,RS,d;p=2
' <log3.txt
And the same logic (except that it will match denied anywhere on the line (not as a word)) in the shell:
#!/bin/sh
p=0
while IFS= read -r line; do
if [ "$p" = 1 ]; then
case $line in
*denied*) deniedline=$line; p=0 ;;
esac
fi
case $line in
Host*) hostline=$line; p=1 ;;
esac
if [ "$p" = 0 ] && [ "$hostline" ] && [ "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
p=2
fi
done <log3.txt
2nd solution doesn't quite work, it prints whatever comes before the first "Host" line and hangs on this input:Host: ok.com/Access OK/Host: denied.com/Access denied.
– xenoid
Dec 3 at 16:44
Yes, the first version assumeddeniedfollowedHost(as it is written on the answer). I made it a lot more robust now. Hard for me to think of a way to break it (until someone figure out how, of course :-) ).
– Isaac
Dec 3 at 21:08
yes 2nd solution it is OR condition
– Widi Anto
Dec 4 at 2:54
and the end solution it is work for me, and it is perfect, thanks.
– Widi Anto
Dec 4 at 2:56
add a comment |
up vote
0
down vote
accepted
If you are sure that the files to process are small (like your example), you can read the whole file in one go and test that:
file=$(<log3.txt)
[[ $file =~ Host ]] && [[ $file =~ denied ]] && echo "$file"
For a larger file, and assuming that Host comes before denied you may use a faster (for external files) sed:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;q;b1'
Understand that this solution will strictly print the first line that starts with Host and the following (not in the same line) first line that contains denied as a word.
If you need to extract several pairs of Host - denied, change the q to a b, that will re-start the cycle:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;b;b1'
A similar solution with awk that will print the last Host line that is just before a denied line (in pairs):
awk ' p==1 && /<denied>/ d=$0;p=0
/^Host*/ h=$0;p=1
if(p==0&&h!=""&&d!="") print h,RS,d;p=2
' <log3.txt
And the same logic (except that it will match denied anywhere on the line (not as a word)) in the shell:
#!/bin/sh
p=0
while IFS= read -r line; do
if [ "$p" = 1 ]; then
case $line in
*denied*) deniedline=$line; p=0 ;;
esac
fi
case $line in
Host*) hostline=$line; p=1 ;;
esac
if [ "$p" = 0 ] && [ "$hostline" ] && [ "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
p=2
fi
done <log3.txt
2nd solution doesn't quite work, it prints whatever comes before the first "Host" line and hangs on this input:Host: ok.com/Access OK/Host: denied.com/Access denied.
– xenoid
Dec 3 at 16:44
Yes, the first version assumeddeniedfollowedHost(as it is written on the answer). I made it a lot more robust now. Hard for me to think of a way to break it (until someone figure out how, of course :-) ).
– Isaac
Dec 3 at 21:08
yes 2nd solution it is OR condition
– Widi Anto
Dec 4 at 2:54
and the end solution it is work for me, and it is perfect, thanks.
– Widi Anto
Dec 4 at 2:56
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
If you are sure that the files to process are small (like your example), you can read the whole file in one go and test that:
file=$(<log3.txt)
[[ $file =~ Host ]] && [[ $file =~ denied ]] && echo "$file"
For a larger file, and assuming that Host comes before denied you may use a faster (for external files) sed:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;q;b1'
Understand that this solution will strictly print the first line that starts with Host and the following (not in the same line) first line that contains denied as a word.
If you need to extract several pairs of Host - denied, change the q to a b, that will re-start the cycle:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;b;b1'
A similar solution with awk that will print the last Host line that is just before a denied line (in pairs):
awk ' p==1 && /<denied>/ d=$0;p=0
/^Host*/ h=$0;p=1
if(p==0&&h!=""&&d!="") print h,RS,d;p=2
' <log3.txt
And the same logic (except that it will match denied anywhere on the line (not as a word)) in the shell:
#!/bin/sh
p=0
while IFS= read -r line; do
if [ "$p" = 1 ]; then
case $line in
*denied*) deniedline=$line; p=0 ;;
esac
fi
case $line in
Host*) hostline=$line; p=1 ;;
esac
if [ "$p" = 0 ] && [ "$hostline" ] && [ "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
p=2
fi
done <log3.txt
If you are sure that the files to process are small (like your example), you can read the whole file in one go and test that:
file=$(<log3.txt)
[[ $file =~ Host ]] && [[ $file =~ denied ]] && echo "$file"
For a larger file, and assuming that Host comes before denied you may use a faster (for external files) sed:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;q;b1'
Understand that this solution will strictly print the first line that starts with Host and the following (not in the same line) first line that contains denied as a word.
If you need to extract several pairs of Host - denied, change the q to a b, that will re-start the cycle:
<log3.txt sed -n '/^Host/!d;p;:1;n;/<denied>/p;b;b1'
A similar solution with awk that will print the last Host line that is just before a denied line (in pairs):
awk ' p==1 && /<denied>/ d=$0;p=0
/^Host*/ h=$0;p=1
if(p==0&&h!=""&&d!="") print h,RS,d;p=2
' <log3.txt
And the same logic (except that it will match denied anywhere on the line (not as a word)) in the shell:
#!/bin/sh
p=0
while IFS= read -r line; do
if [ "$p" = 1 ]; then
case $line in
*denied*) deniedline=$line; p=0 ;;
esac
fi
case $line in
Host*) hostline=$line; p=1 ;;
esac
if [ "$p" = 0 ] && [ "$hostline" ] && [ "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
p=2
fi
done <log3.txt
edited Dec 4 at 2:59
answered Dec 3 at 10:23
Isaac
10.9k11448
10.9k11448
2nd solution doesn't quite work, it prints whatever comes before the first "Host" line and hangs on this input:Host: ok.com/Access OK/Host: denied.com/Access denied.
– xenoid
Dec 3 at 16:44
Yes, the first version assumeddeniedfollowedHost(as it is written on the answer). I made it a lot more robust now. Hard for me to think of a way to break it (until someone figure out how, of course :-) ).
– Isaac
Dec 3 at 21:08
yes 2nd solution it is OR condition
– Widi Anto
Dec 4 at 2:54
and the end solution it is work for me, and it is perfect, thanks.
– Widi Anto
Dec 4 at 2:56
add a comment |
2nd solution doesn't quite work, it prints whatever comes before the first "Host" line and hangs on this input:Host: ok.com/Access OK/Host: denied.com/Access denied.
– xenoid
Dec 3 at 16:44
Yes, the first version assumeddeniedfollowedHost(as it is written on the answer). I made it a lot more robust now. Hard for me to think of a way to break it (until someone figure out how, of course :-) ).
– Isaac
Dec 3 at 21:08
yes 2nd solution it is OR condition
– Widi Anto
Dec 4 at 2:54
and the end solution it is work for me, and it is perfect, thanks.
– Widi Anto
Dec 4 at 2:56
2nd solution doesn't quite work, it prints whatever comes before the first "Host" line and hangs on this input:
Host: ok.com/Access OK/Host: denied.com/Access denied.– xenoid
Dec 3 at 16:44
2nd solution doesn't quite work, it prints whatever comes before the first "Host" line and hangs on this input:
Host: ok.com/Access OK/Host: denied.com/Access denied.– xenoid
Dec 3 at 16:44
Yes, the first version assumed
denied followed Host (as it is written on the answer). I made it a lot more robust now. Hard for me to think of a way to break it (until someone figure out how, of course :-) ).– Isaac
Dec 3 at 21:08
Yes, the first version assumed
denied followed Host (as it is written on the answer). I made it a lot more robust now. Hard for me to think of a way to break it (until someone figure out how, of course :-) ).– Isaac
Dec 3 at 21:08
yes 2nd solution it is OR condition
– Widi Anto
Dec 4 at 2:54
yes 2nd solution it is OR condition
– Widi Anto
Dec 4 at 2:54
and the end solution it is work for me, and it is perfect, thanks.
– Widi Anto
Dec 4 at 2:56
and the end solution it is work for me, and it is perfect, thanks.
– Widi Anto
Dec 4 at 2:56
add a comment |
up vote
2
down vote
In any single iteration of your while loop, the value $LINE can't be both Host and denied. It's impossible given the data in the file. This is why you get no output.
If you want to see all lines in the file that matches the two words Host or denied, use grep instead:
grep -wF -e 'Host' -e 'Access denied' <log3.txt
The options used here will ensure that we are doing string comparisons rather than regular expression matches (-F) and that we are matching complete words and not substrings (-w). The two query strings are given with -e and we'll get any line containing any of these.
If you want to make a slightly more advanced query, which only shows the lines that contains the two words if they both appear in the file, then you could do it with an awk program instead:
awk '/Host/ hostline=$0 /Access denied/ deniedline=$0
END if ((hostline != "") && (deniedline != ""))
print hostline; print deniedline; ' <log3.txt
Here, if we find a line matching the string Host, we save it, and likewise for the string Access denied. At the end, if both strings contain anything, we print them.
In more or less equivalent shell code:
#!/bin/sh
while IFS= read -r line; do
case $line in
*Host*)
hostline=$line ;;
*"Access denied"*)
deniedline=$line ;;
esac
done <log3.txt
if [ -n "$hostline" ] && [ -n "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
fi
Here I use a case ... esac statement to do the matching on the read data. The patterns used are filename globbing patterns, not regular expressions.
Related:
- Understanding "IFS= read -r line"
- Why is using a shell loop to process text considered bad practice?
awkcode doesn't seem to work, try withHost: denied1.com/Access denied/Host: ok.com/Access OK/Host: random.com. The question is hard to answer since we don't know what the rest of the file looks like.
– xenoid
Dec 3 at 9:37
@xenoid I've made it slightly more robust, but you are correct that the intended behaviour is unclear.
– Kusalananda
Dec 3 at 9:48
@Kusalananda thanks it works for me
– Widi Anto
Dec 3 at 10:12
Notes worth adding: The grep code will print any line with eitherHostorAccess denied, not as pairs. The awk solution will only print the last instance of the pair. The shell solution will matchHostat any position on the line and will only print the lastHostand the lastAccess deniedfound.
– Isaac
Dec 3 at 21:43
@Kusalananda grep -wF -e 'Host' -e 'Access denied' <log3.txt it is OR condtions, so it works for me when using use case ... esac
– Widi Anto
Dec 4 at 2:29
|
show 1 more comment
up vote
2
down vote
In any single iteration of your while loop, the value $LINE can't be both Host and denied. It's impossible given the data in the file. This is why you get no output.
If you want to see all lines in the file that matches the two words Host or denied, use grep instead:
grep -wF -e 'Host' -e 'Access denied' <log3.txt
The options used here will ensure that we are doing string comparisons rather than regular expression matches (-F) and that we are matching complete words and not substrings (-w). The two query strings are given with -e and we'll get any line containing any of these.
If you want to make a slightly more advanced query, which only shows the lines that contains the two words if they both appear in the file, then you could do it with an awk program instead:
awk '/Host/ hostline=$0 /Access denied/ deniedline=$0
END if ((hostline != "") && (deniedline != ""))
print hostline; print deniedline; ' <log3.txt
Here, if we find a line matching the string Host, we save it, and likewise for the string Access denied. At the end, if both strings contain anything, we print them.
In more or less equivalent shell code:
#!/bin/sh
while IFS= read -r line; do
case $line in
*Host*)
hostline=$line ;;
*"Access denied"*)
deniedline=$line ;;
esac
done <log3.txt
if [ -n "$hostline" ] && [ -n "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
fi
Here I use a case ... esac statement to do the matching on the read data. The patterns used are filename globbing patterns, not regular expressions.
Related:
- Understanding "IFS= read -r line"
- Why is using a shell loop to process text considered bad practice?
awkcode doesn't seem to work, try withHost: denied1.com/Access denied/Host: ok.com/Access OK/Host: random.com. The question is hard to answer since we don't know what the rest of the file looks like.
– xenoid
Dec 3 at 9:37
@xenoid I've made it slightly more robust, but you are correct that the intended behaviour is unclear.
– Kusalananda
Dec 3 at 9:48
@Kusalananda thanks it works for me
– Widi Anto
Dec 3 at 10:12
Notes worth adding: The grep code will print any line with eitherHostorAccess denied, not as pairs. The awk solution will only print the last instance of the pair. The shell solution will matchHostat any position on the line and will only print the lastHostand the lastAccess deniedfound.
– Isaac
Dec 3 at 21:43
@Kusalananda grep -wF -e 'Host' -e 'Access denied' <log3.txt it is OR condtions, so it works for me when using use case ... esac
– Widi Anto
Dec 4 at 2:29
|
show 1 more comment
up vote
2
down vote
up vote
2
down vote
In any single iteration of your while loop, the value $LINE can't be both Host and denied. It's impossible given the data in the file. This is why you get no output.
If you want to see all lines in the file that matches the two words Host or denied, use grep instead:
grep -wF -e 'Host' -e 'Access denied' <log3.txt
The options used here will ensure that we are doing string comparisons rather than regular expression matches (-F) and that we are matching complete words and not substrings (-w). The two query strings are given with -e and we'll get any line containing any of these.
If you want to make a slightly more advanced query, which only shows the lines that contains the two words if they both appear in the file, then you could do it with an awk program instead:
awk '/Host/ hostline=$0 /Access denied/ deniedline=$0
END if ((hostline != "") && (deniedline != ""))
print hostline; print deniedline; ' <log3.txt
Here, if we find a line matching the string Host, we save it, and likewise for the string Access denied. At the end, if both strings contain anything, we print them.
In more or less equivalent shell code:
#!/bin/sh
while IFS= read -r line; do
case $line in
*Host*)
hostline=$line ;;
*"Access denied"*)
deniedline=$line ;;
esac
done <log3.txt
if [ -n "$hostline" ] && [ -n "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
fi
Here I use a case ... esac statement to do the matching on the read data. The patterns used are filename globbing patterns, not regular expressions.
Related:
- Understanding "IFS= read -r line"
- Why is using a shell loop to process text considered bad practice?
In any single iteration of your while loop, the value $LINE can't be both Host and denied. It's impossible given the data in the file. This is why you get no output.
If you want to see all lines in the file that matches the two words Host or denied, use grep instead:
grep -wF -e 'Host' -e 'Access denied' <log3.txt
The options used here will ensure that we are doing string comparisons rather than regular expression matches (-F) and that we are matching complete words and not substrings (-w). The two query strings are given with -e and we'll get any line containing any of these.
If you want to make a slightly more advanced query, which only shows the lines that contains the two words if they both appear in the file, then you could do it with an awk program instead:
awk '/Host/ hostline=$0 /Access denied/ deniedline=$0
END if ((hostline != "") && (deniedline != ""))
print hostline; print deniedline; ' <log3.txt
Here, if we find a line matching the string Host, we save it, and likewise for the string Access denied. At the end, if both strings contain anything, we print them.
In more or less equivalent shell code:
#!/bin/sh
while IFS= read -r line; do
case $line in
*Host*)
hostline=$line ;;
*"Access denied"*)
deniedline=$line ;;
esac
done <log3.txt
if [ -n "$hostline" ] && [ -n "$deniedline" ]; then
printf '%sn%sn' "$hostline" "$deniedline"
fi
Here I use a case ... esac statement to do the matching on the read data. The patterns used are filename globbing patterns, not regular expressions.
Related:
- Understanding "IFS= read -r line"
- Why is using a shell loop to process text considered bad practice?
edited Dec 3 at 9:47
answered Dec 3 at 7:31
Kusalananda
119k16223365
119k16223365
awkcode doesn't seem to work, try withHost: denied1.com/Access denied/Host: ok.com/Access OK/Host: random.com. The question is hard to answer since we don't know what the rest of the file looks like.
– xenoid
Dec 3 at 9:37
@xenoid I've made it slightly more robust, but you are correct that the intended behaviour is unclear.
– Kusalananda
Dec 3 at 9:48
@Kusalananda thanks it works for me
– Widi Anto
Dec 3 at 10:12
Notes worth adding: The grep code will print any line with eitherHostorAccess denied, not as pairs. The awk solution will only print the last instance of the pair. The shell solution will matchHostat any position on the line and will only print the lastHostand the lastAccess deniedfound.
– Isaac
Dec 3 at 21:43
@Kusalananda grep -wF -e 'Host' -e 'Access denied' <log3.txt it is OR condtions, so it works for me when using use case ... esac
– Widi Anto
Dec 4 at 2:29
|
show 1 more comment
awkcode doesn't seem to work, try withHost: denied1.com/Access denied/Host: ok.com/Access OK/Host: random.com. The question is hard to answer since we don't know what the rest of the file looks like.
– xenoid
Dec 3 at 9:37
@xenoid I've made it slightly more robust, but you are correct that the intended behaviour is unclear.
– Kusalananda
Dec 3 at 9:48
@Kusalananda thanks it works for me
– Widi Anto
Dec 3 at 10:12
Notes worth adding: The grep code will print any line with eitherHostorAccess denied, not as pairs. The awk solution will only print the last instance of the pair. The shell solution will matchHostat any position on the line and will only print the lastHostand the lastAccess deniedfound.
– Isaac
Dec 3 at 21:43
@Kusalananda grep -wF -e 'Host' -e 'Access denied' <log3.txt it is OR condtions, so it works for me when using use case ... esac
– Widi Anto
Dec 4 at 2:29
awk code doesn't seem to work, try with Host: denied1.com/Access denied/Host: ok.com/Access OK/Host: random.com. The question is hard to answer since we don't know what the rest of the file looks like.– xenoid
Dec 3 at 9:37
awk code doesn't seem to work, try with Host: denied1.com/Access denied/Host: ok.com/Access OK/Host: random.com. The question is hard to answer since we don't know what the rest of the file looks like.– xenoid
Dec 3 at 9:37
@xenoid I've made it slightly more robust, but you are correct that the intended behaviour is unclear.
– Kusalananda
Dec 3 at 9:48
@xenoid I've made it slightly more robust, but you are correct that the intended behaviour is unclear.
– Kusalananda
Dec 3 at 9:48
@Kusalananda thanks it works for me
– Widi Anto
Dec 3 at 10:12
@Kusalananda thanks it works for me
– Widi Anto
Dec 3 at 10:12
Notes worth adding: The grep code will print any line with either
Host or Access denied, not as pairs. The awk solution will only print the last instance of the pair. The shell solution will match Host at any position on the line and will only print the last Host and the last Access denied found.– Isaac
Dec 3 at 21:43
Notes worth adding: The grep code will print any line with either
Host or Access denied, not as pairs. The awk solution will only print the last instance of the pair. The shell solution will match Host at any position on the line and will only print the last Host and the last Access denied found.– Isaac
Dec 3 at 21:43
@Kusalananda grep -wF -e 'Host' -e 'Access denied' <log3.txt it is OR condtions, so it works for me when using use case ... esac
– Widi Anto
Dec 4 at 2:29
@Kusalananda grep -wF -e 'Host' -e 'Access denied' <log3.txt it is OR condtions, so it works for me when using use case ... esac
– Widi Anto
Dec 4 at 2:29
|
show 1 more comment
up vote
0
down vote
See @Kusalananda answer for why your solution doesn't work.
My solution using grep -z:
grep -zEo -e 'Host: (w|.)+s+Access denieds' log.txt
In slo-mo:
-E: use extended regexp-o: print matches only-z: useas line delimiters. Since there are none, the search is done on the whole file, wherenis just a plain character.- e'Host: (w|.)+s+Access denieds': look for:- "
Host:" - A sequence of letter, digits, or dots
- A space-class character (which is going to be
n) - "
Access denied" - A space-class character (which is going to be
n). This one is need to get a linefeed on output
- "
Running on:
Host: denied1.com
Access denied
Host: ok.com
Access OK
Host: random.com
Host: denied2.com
Access denied
More stuff
Yields:
Host: denied1.com
Access denied
Host: denied2.com
Access denied
this is not work for me, there'is no results after running the command
– Widi Anto
Dec 4 at 2:58
What is the input? Works for me with your two-lines data if the last line ends with a linefeed (like all Linux logs do). If you want to the command to work even it if it is missing, just add a?at the end of the regexp:'Host: (w|.)+sAccess denieds?'
– xenoid
Dec 4 at 7:41
add a comment |
up vote
0
down vote
See @Kusalananda answer for why your solution doesn't work.
My solution using grep -z:
grep -zEo -e 'Host: (w|.)+s+Access denieds' log.txt
In slo-mo:
-E: use extended regexp-o: print matches only-z: useas line delimiters. Since there are none, the search is done on the whole file, wherenis just a plain character.- e'Host: (w|.)+s+Access denieds': look for:- "
Host:" - A sequence of letter, digits, or dots
- A space-class character (which is going to be
n) - "
Access denied" - A space-class character (which is going to be
n). This one is need to get a linefeed on output
- "
Running on:
Host: denied1.com
Access denied
Host: ok.com
Access OK
Host: random.com
Host: denied2.com
Access denied
More stuff
Yields:
Host: denied1.com
Access denied
Host: denied2.com
Access denied
this is not work for me, there'is no results after running the command
– Widi Anto
Dec 4 at 2:58
What is the input? Works for me with your two-lines data if the last line ends with a linefeed (like all Linux logs do). If you want to the command to work even it if it is missing, just add a?at the end of the regexp:'Host: (w|.)+sAccess denieds?'
– xenoid
Dec 4 at 7:41
add a comment |
up vote
0
down vote
up vote
0
down vote
See @Kusalananda answer for why your solution doesn't work.
My solution using grep -z:
grep -zEo -e 'Host: (w|.)+s+Access denieds' log.txt
In slo-mo:
-E: use extended regexp-o: print matches only-z: useas line delimiters. Since there are none, the search is done on the whole file, wherenis just a plain character.- e'Host: (w|.)+s+Access denieds': look for:- "
Host:" - A sequence of letter, digits, or dots
- A space-class character (which is going to be
n) - "
Access denied" - A space-class character (which is going to be
n). This one is need to get a linefeed on output
- "
Running on:
Host: denied1.com
Access denied
Host: ok.com
Access OK
Host: random.com
Host: denied2.com
Access denied
More stuff
Yields:
Host: denied1.com
Access denied
Host: denied2.com
Access denied
See @Kusalananda answer for why your solution doesn't work.
My solution using grep -z:
grep -zEo -e 'Host: (w|.)+s+Access denieds' log.txt
In slo-mo:
-E: use extended regexp-o: print matches only-z: useas line delimiters. Since there are none, the search is done on the whole file, wherenis just a plain character.- e'Host: (w|.)+s+Access denieds': look for:- "
Host:" - A sequence of letter, digits, or dots
- A space-class character (which is going to be
n) - "
Access denied" - A space-class character (which is going to be
n). This one is need to get a linefeed on output
- "
Running on:
Host: denied1.com
Access denied
Host: ok.com
Access OK
Host: random.com
Host: denied2.com
Access denied
More stuff
Yields:
Host: denied1.com
Access denied
Host: denied2.com
Access denied
answered Dec 3 at 16:38
xenoid
2,6701724
2,6701724
this is not work for me, there'is no results after running the command
– Widi Anto
Dec 4 at 2:58
What is the input? Works for me with your two-lines data if the last line ends with a linefeed (like all Linux logs do). If you want to the command to work even it if it is missing, just add a?at the end of the regexp:'Host: (w|.)+sAccess denieds?'
– xenoid
Dec 4 at 7:41
add a comment |
this is not work for me, there'is no results after running the command
– Widi Anto
Dec 4 at 2:58
What is the input? Works for me with your two-lines data if the last line ends with a linefeed (like all Linux logs do). If you want to the command to work even it if it is missing, just add a?at the end of the regexp:'Host: (w|.)+sAccess denieds?'
– xenoid
Dec 4 at 7:41
this is not work for me, there'is no results after running the command
– Widi Anto
Dec 4 at 2:58
this is not work for me, there'is no results after running the command
– Widi Anto
Dec 4 at 2:58
What is the input? Works for me with your two-lines data if the last line ends with a linefeed (like all Linux logs do). If you want to the command to work even it if it is missing, just add a
? at the end of the regexp: 'Host: (w|.)+sAccess denieds?'– xenoid
Dec 4 at 7:41
What is the input? Works for me with your two-lines data if the last line ends with a linefeed (like all Linux logs do). If you want to the command to work even it if it is missing, just add a
? at the end of the regexp: 'Host: (w|.)+sAccess denieds?'– xenoid
Dec 4 at 7:41
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f485613%2fbash-script-read-text-files-using-and-conditions-with-different-lines%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown