Hi,
Below is the command I use to search for IP address in a file.
find ./ -type f \( -name "*.txt" -or -name "*.xml" \) | xargs grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"
As an output I found three IP address and below is how they look.
#Listen 112.34.56.58:80
Listen 112.134.56.58:80 #This is an IP
Listen 112.34.55.58:80
The problem is I do not want any IP in output which begin with "#" i.e
# Listen 12.34.56.78:80
Because, in my case anything starting with a # usually means comments and should be ignored i.e not listed.
Can you please tell me how should I tweak my command not to display IPs mentioned in lines that start with "#" character?
Please note: Any "#" after the IP should be considered and grep like below:
Listen 112.134.56.58:80 #This is an IP
Thank you.
Maybe using an additional step to get just the IP address. Something like:
find ./ -type f \( -name "*.txt" -or -name "*.xml" \) | xargs grep -oE "^ *[^#].*\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"
or
find ./ -type f \( -name "*.txt" -or -name "*.xml" \) | xargs grep -oE "^ *[^#].*\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | awk '{print $NF}'
If your grep has the -P
option you could use a lookahead to discard commented IPs.
Also here I added some more validation to discard illegal IP addresses (eg 192.999.1.1):
... | xargs grep -oP '[^#]*\b\K(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|\b)){4})'
grep -o breaks the rule "grep returns whole lines".
So combining it with other options like -v produces experimental results.
Rather than trying the experimental -P that might differ between grep versions, I would go to real perl, like
perl -lne '/^[^#]*\b((\d{1,3}[.]){3}\d{1,3})\b/ and print $1'
or
perl -lne 's/#.*//; /\b((\d{1,3}[.]){3}\d{1,3})\b/ and print $1'
The latter leads to sed, indeed you can use sed to pre-filter the lines and then pipe to grep
sed 's/#.*//' | grep -Eo '\b([0-9]{1,3}[.]){3}[0-9]{1,3}\b'
I tried all the suggestions but none of the helped.
A file has the below entries
#Listen 112.34.56.58:80
Listen 112.134.56.58:80 #This is an IP
Listen 112.34.55.58:80
Expectation is that the search should yield 2 / 3 IPs mentioned in the file. Yes, the entry which starts with the hash(#) i.e. #Listen 112.34.56.58:80
should not be display.
However, all the three entries are displayed which are listed in the file. One can create a file with these entries and test to see the problem themselves.
Can you please suggest please?
For me it works
cat file
#Listen 112.34.56.58:80
Listen 112.134.56.58:80 #This is an IP
Listen 112.34.55.58:80
perl -lne 's/#.*//; /\b((\d{1,3}[.]){3}\d{1,3})\b/ and print $1' file
112.134.56.58
112.34.55.58
perl -lne '/^[^#]*\b((\d{1,3}[.]){3}\d{1,3})\b/ and print $1' file
112.134.56.58
112.34.55.58
sed 's/#.*//' file | grep -Eo '\b([0-9]{1,3}[.]){3}[0-9]{1,3}\b'
112.134.56.58
112.34.55.58
Could you please copy/paste your command/result?
I m trying the below command but I do not see any output even when I expect it to.
sed 's/#.*//' | find ./ -type f \( -name "*.txt" -or -name "*.xml" \) | grep -Eo '\b([0-9]{1,3}[.]){3}[0-9]{1,3}\b'
I do not wish to use perl.
Here is my OS details: Linux mycomp 3.10.0-693.17.1.el7.x86_64 #1 SMP Sun Jan 14 10:36:03 EST 2018 x86_64 x86_64 x86_64 GNU/Linux
I was anyways able to get this to work by rewriting the command as a script.
for i in $( find ./ -type f \( -name "*.txt" -or -name "*.xml" \) );
do
sed 's/#.*//' "$i" | grep -Eo '\b([0-9]{1,3}[.]){3}[0-9]{1,3}\b'
if [ $? -eq 0 ]; then
echo "File:$i"
fi
done
find does not read from stdin, and sed needs an input (filename as argument or stdin).
Your script is okay.
If you take a while read loop and quote the variables that holds filenames, then it is even takes filenames with special characters.
find ./ -type f \( -name "*.txt" -o -name "*.xml" \) |
while IFS= read -r f
do
if ips=$(sed 's/#.*//' "$f" | grep -Eo '\b([0-9]{1,3}[.]){3}[0-9]{1,3}\b')
then
echo "File:$f"
echo "$ips"
fi
done
The if
takes the exit status from the last command i.e. the grep
(0 gives true).
One could as well test the variable of being non-null.
The quotes in echo "$ips"
keep the newlines in the variable, while echo $ips
would print them in a row (and the shell tries to glob them, but you have ensured it does not have special glob characters).
1 Like