Using egrep to search for IP address by octets from a shell variable - bash

I'm writing a BASH script that outputs iptables -L -n and searches for the existence of an IP address. I'm stuck with how to use this with egrep. Roughly:
CHECK=$(iptables -L -n | egrep $the_string)
which "looks" like it would work, but it doesn't have an end delimiter $ so it would match:
25.24.244
and
25.24.24
When I really just need to match for 25.24.24 only.
I tried escaping this but the $ creates issues with the regular expression.
At least this is the only means I've found to search for the IP in the iptables system. It doesn't appear to have any query mechanism itself (puzzling).
I am probably missing something very simple here, and just need a pointer or two :-)
Thanks.

You should backslash the . : this means any character in regex...
iptables -L -n | grep "25\.24\.24$"
(no need egrep there)

The $ at the end of the regular expression works as expected:
the_ip=25.24.24
the_string=$(echo $the_ip | sed 's/\./\\\./g')
iptables -L -n | egrep "$the_string$"

Related

nslookup/dig/drill commands on a file that contains websites to add ip addresses

UPDATE : Still open for solutions using nslookup without parallel, dig or drill
I need to write a script that scans a file containing web page addresses on each line, and adds to these lines the IP address corresponding to the name using nslookup command. The script looks like this at the moment :
#!/usr/bin/
while read ip
do
nslookup "$ip" |
awk '/Name:/{val=$NF;flag=1;next} /Address:/ &&
flag{print val,$NF;val=""}' |
sed -n 'p;n'
done < is8.input
The input file contains the following websites :
www.edu.ro
vega.unitbv.ro
www.wikipedia.org
The final output should look like :
www.edu.ro 193.169.21.181
vega.unitbv.ro 193.254.231.35
www.wikipedia.org 91.198.174.192
The main problem i have with the current state of the script is that it takes the names from nslookup (which is good for www.edu.ro) instead of taking the aliases when those are available. My output looks like this:
www.edu.ro 193.169.21.181
etc.unitbv.ro 193.254.231.35
dyna.wikimedia.org 91.198.174.192
I was thinking about implementing a if-else for aliases but i don't know how to do one on the current command. Also the script can be changed if anyone has a better understanding of how to format nslookup to show it like the output given.
Minimalist workaround quasi-answer. Here's a one-liner replacement for the script using GNU parallel, host (less work to parse than nslookup), and sed:
parallel "host {} 2> /dev/null |
sed -n '/ has address /{s/.* /'{}' /p;q}'" < is8.input
...or using nslookup at the cost of added GNU sed complexity.
parallel "nslookup {} 2> /dev/null |
sed -n '/^A/{s/.* /'{}' /;T;p;q;}'" < is8.input
...or using xargs:
xargs -I '{}' sh -c \
"nslookup {} 2> /dev/null |
sed -n '/^A/{s/.* /'{}' /;T;p;q;}'" < is8.input
Output of any of those:
www.edu.ro 193.169.21.181
vega.unitbv.ro 193.254.231.35
www.wikipedia.org 208.80.154.224
Replace your complete nslookup line with:
echo "$IP $(dig +short "$IP" | grep -m 1 -E '^[0-9.]{7,15}$')"
This might work for you (GNU sed and host):
sed '/\S/{s#.*#host & | sed -n "/ has address/{s///p;q}"#e}' file
For all non-empty lines: invoke the host command on the supplied host name and pipe the results to another invocation of sed which strips out text and quits after the first result.

Grep multiple strings from text file

Okay so I have a textfile containing multiple strings, example of this -
Hello123
Halo123
Gracias
Thank you
...
I want grep to use these strings to find lines with matching strings/keywords from other files within a directory
example of text files being grepped -
123-example-Halo123
321-example-Gracias-com-no
321-example-match
so in this instance the output should be
123-example-Halo123
321-example-Gracias-com-no
With GNU grep:
grep -f file1 file2
-f FILE: Obtain patterns from FILE, one per line.
Output:
123-example-Halo123
321-example-Gracias-com-no
You should probably look at the manpage for grep to get a better understanding of what options are supported by the grep utility. However, there a number of ways to achieve what you're trying to accomplish. Here's one approach:
grep -e "Hello123" -e "Halo123" -e "Gracias" -e "Thank you" list_of_files_to_search
However, since your search strings are already in a separate file, you would probably want to use this approach:
grep -f patternFile list_of_files_to_search
I can think of two possible solutions for your question:
Use multiple regular expressions - a regular expression for each word you want to find, for example:
grep -e Hello123 -e Halo123 file_to_search.txt
Use a single regular expression with an "or" operator. Using Perl regular expressions, it will look like the following:
grep -P "Hello123|Halo123" file_to_search.txt
EDIT:
As you mentioned in your comment, you want to use a list of words to find from a file and search in a full directory.
You can manipulate the words-to-find file to look like -e flags concatenation:
cat words_to_find.txt | sed 's/^/-e "/;s/$/"/' | tr '\n' ' '
This will return something like -e "Hello123" -e "Halo123" -e "Gracias" -e" Thank you", which you can then pass to grep using xargs:
cat words_to_find.txt | sed 's/^/-e "/;s/$/"/' | tr '\n' ' ' | dir_to_search/*
As you can see, the last command also searches in all of the files in the directory.
SECOND EDIT: as PesaThe mentioned, the following command would do this in a much more simple and elegant way:
grep -f words_to_find.txt dir_to_search/*

grep exact string by pattern in variable

I want to grep exact string by pattern in variable
ip="192.168.100.1"
arp -a | grep "$ip"
This outputs something like this:
# arp -a | grep "$ip"
? (192.168.10.1) at 66:ca:6d:88:57:cd [ether] on br0
? (192.168.10.15) at 3c:15:a0:05:b5:94 [ether] on br0
but I want exactly IP no IP of other PCs
Also I have only embedded grep (minimalistic) also I have awk,sed.
Im trying this but without success:
arp -a | grep "\b$ip\b"
Word boundaries like \b aren't available with standard grep. From the output snippet you posted it looks like this will work for you:
$ ip="192.168.10.1"
$ grep -F "($ip)" file
? (192.168.10.1) at 66:ca:6d:88:57:cd [ether] on br0
i.e. just use -F for a string instead of regexp comparison and explicitly include the delimiters that appear around the IP address in the input.
FWIW in awk it'd be:
$ awk -v ip="($ip)" 'index($0,ip)' file
? (192.168.10.1) at 66:ca:6d:88:57:cd [ether] on br0
and you can't do it in a reasonable way in sed since sed ONLY supports regexp comparisons, not strings (see Is it possible to escape regex metacharacters reliably with sed).
If I understand correctly what you are saying you just want to add a -o option to your command, the -o option print only the matched (non-empty) parts of a matching line,with each such part on a separate output line.
arp -a | grep -o "$ip"

grepping string from long text

The command below in OSX checks whether an account is disabled (or not).
I'd like to grep the string "isDisabled=X" to create a report of disabled users, but am not sure how to do this since the output is on three lines, and I'm interested in the first 12 characters of line three:
bash-3.2# pwpolicy -u jdoe -getpolicy
Getting policy for jdoe /LDAPv3/127.0.0.1
isDisabled=0 isAdminUser=1 newPasswordRequired=0 usingHistory=0 canModifyPasswordforSelf=1 usingExpirationDate=0 usingHardExpirationDate=0 requiresAlpha=0 requiresNumeric=0 expirationDateGMT=12/31/69 hardExpireDateGMT=12/31/69 maxMinutesUntilChangePassword=0 maxMinutesUntilDisabled=0 maxMinutesOfNonUse=0 maxFailedLoginAttempts=0 minChars=0 maxChars=0 passwordCannotBeName=0 validAfter=01/01/70 requiresMixedCase=0 requiresSymbol=0 notGuessablePattern=0 isSessionKeyAgent=0 isComputerAccount=0 adminClass=0 adminNoChangePasswords=0 adminNoSetPolicies=0 adminNoCreate=0 adminNoDelete=0 adminNoClearState=0 adminNoPromoteAdmins=0
Your ideas/suggestions are most appreciated! Ultimately this will be part of a Bash script. Thanks.
This is how you would use grep to match "isDisabled=X":
grep -o "isDisabled=."
Explanation:
grep: invoke the grep command
-o: Use the --only-matching option for grep (From grep manual: "Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line."
"isDisabled=.": This is the search pattern you give to grep. The . is part of the regular expression, it means "match any character except for newline".
Usage:
This is how you would use it as part of your script:
pwpolicy -u jdoe -getpolicy | grep -oE "isDisabled=."
This is how you can save the result to a variable:
status=$(pwpolicy -u jdoe -getpolicy | grep -oE "isDisabled=.")
If your command was run some time prior, and the results from the command was saved to a file called "results.txt", you use it as input to grep as follows:
grep -o "isDisabled=." results.txt
You can use sed as
cat results.txt | sed -n 's/.*isDisabled=\(.\).*/\1/p'
This will print the value of isDisbaled.

Get open ports as an array

So, I'm using netstat -lt to get open ports. However, I'm not interested in certain values (like SSH or 22), so I want to be able to exclude them. I also want to get them as an array in bash. So far I have netstat -lt | sed -r 's/tcp[^:]+://g' | cut -d' ' -f1 but they're not an array, nor am I excluding anything.
Try using the ss command, which replaces netstat.
ss -atu | awk '{print $5}' | awk -F: '{print $NF}'
The ss command gives you all TCP and UDP ports on the local machine (the only sockets that would have ports). The first awk extracts the column containing the local address and port number. The second awk takes only the last field following a colon; this is necessary in case you have IPv6 sockets on your machine, whose IP address will also include colons.
Once you've done this, you can grep out the ports you don't want. Also, see the documentation referred to by the ss man page for information on filters, which may let you filter out unwanted sockets from the output of ss.
Add ($()) around your statement:
port=($(netstat -ltn | sed -rne '/^tcp/{/:(22|25)\>/d;s/.*:([0-9]+)\>.*/\1/p}'))
Filtering ports 22 and 25.
a=( `netstat -ltn --inet | sed -r -e '1,2d''s/tcp[^:]+://g' | cut -d' ' -f1 | sed -e '1,2d' | grep -v "22\|33\|25"` )
second sed command removes headers if your version of netstat prints such. I have "Active" and "Proto" as first two lines. Use grep to filter unwanted ports. add -n to netstat to see port numbers instead of names. --inet is to force ipv4, otherwise you may see IPv6 which may confuse your script.
btw not sure you need an array. usually arrays are needed only if you are going to work on a subset of values you have. If you work on all values there are simpler constructs but not sure what you're going to do.
Regards.
update: you can use a single sed command with two operations instead of two separate invocations:
sed -r -e '1,2d' -e 's/tcp[^:]+://g'

Resources