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"
Related
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.
I would like to grep a number of documents by using a set of search terms and to specify the number of characters after match. Here is what I tried
grep -F -o -P "$(<search.txt).{0,4}" foo.txt
but I get the message 'grep: conflicting matchers specified' because -F and '-oP' cannot be combined. It does not work with '-E' either.
-F and -P are conflicting options, simple as that. The first means that the patterns are fixed strings, the second means that the patterns are Perl-compatible regular expressions. Perhaps you meant to use -f instead, which reads patterns from a file or a process substitution.
If you want to match any of the patterns in your file, followed by 4 characters, you could use something like this
grep -oP -f <(awk '{print $0 ".{4}"}' search.txt) file
This dynamically adds the pattern to each line in the file.
Alternatively, a more portable and concise version would be this:
sed 's/$/.{0,4}/' search.txt | grep -f - -oP file
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$"
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.
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'