Get line by index from grep output - regex

I'm trying to get the machine's ipv4 address.
I've got this working but is there a way to specify you want index 2 from the returned data?
ip a | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"
Output
127.0.0.1
192.168.13.131
192.168.13.255

With awk, please try following, written as per your attempt.
ip a |
awk '
match($0,/([0-9]{1,3}\.){3}[0-9]{1,3}/) && ++count==2{
print substr($0,RSTART,RLENGTH)
}'
Explanation: Adding detailed explanation for above solution.
ip a |
##Running ip a command and sending its output to awk as input
awk '
##Starting awk program from here.
match($0,/([0-9]{1,3}\.){3}[0-9]{1,3}/) && ++count==2{
##Using match function to match IP address and checking if its 2nd time coming.
print substr($0,RSTART,RLENGTH)
##Printing matching sub string here.
}'

One option is to pipe it to sed and print the second line
ip a | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}" | sed -n 2p
Another option could be using a combination of head and tail, showing the first n items with head and then take the last item from that result.
ip a | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}" | head -n2 | tail -n1
If -P is supported for pcre, you might also use a longer pattern, repeating matching the ip number n times using a quantifier, for example {2} for repeating 2 times.
Then use \K to clear the match buffer and output only the ip number of interest.
ip a | grep -Poz "(?s)\A(?:.*?(?:[0-9]{1,3}\.){3}[0-9]{1,3}){2}.*?\K(?:[0-9]{1,3}\.){3}[0-9]{1,3}"
^^^ quantifier

Related

Pull A Section Of A Grepped Line

I need help pulling Bluetooth addresses from a grepped line.
The addresses are like so:
address: 80-82-23-aa-1d-6f, not connected, not favourite, paired, name: "DeviceName", recent access date: 2019-07-22 02:24:44 +0000
address: 4c-6b-e8-01-6d-1e, not connected, not favourite, paired, name: "OtherHeadPhones", recent access date: -
I'm able to grep a line for the device I want, where '$1' is a device name and believe I need to pipe this into a regex grep, but can't workout the regex statement.
blueutil --paired | grep '$1' | grep <something>
I'd require the address line like: '80-82-23-aa-1d-df'. For whichever device name I pass the script ($1)
Any help, and explanation would be much appreciated!
Thanks
blueutil --paired | grep '(your regex returning only the line(s) you want)' | grep -P -o '[\da-f]{2}(-[\da-f]{2}){5}' should help.
-P means that the regex is Perl-compatible.
-o means that only the matches are to be output.
[\da-f] is a hexadecimal digit.
{2} meads that there are two of them in each address part.
{5} means that the address consists of six parts, but the first part, without a hyphen before, has already been matched.
Probably Awk is a better solution in terms of legibility and maintainability.
blueutil --paired |
awk -v pattern="$1" '$0 ~ "name: \042" pattern "\042" {
addr = $2; sub(",", "", addr); print addr }'
This contains some guesswork as to which part of the output from blueutil you want to match -- in particular, it interpolates the input to search for the string in double quotes after name: and a single space.
You can do it using GNU sed:
grep "$1" file_name|sed -r 's/address: (.*),\s+not connected.*/\1/'

Get the following character which match a string

I'm trying to retreive a specific data returned from a command line. Here is my command line:
snmpwalk -v2c -c community localhost 1.3.6.1.2.1.2 | grep tun0
Which give me as result:
IF-MIB::ifDescr.4 = STRING: tun0
In this result I want to retreive 4. I thought using regex, but maybe there is an easier way to fetch it.
Regex I tried :
\ifDescr.\s+\K\S+ https://regex101.com/r/9X04MD/1
[\n\r].*ifDescr.\s*([^\n\r]*) https://regex101.com/r/9X04MD/2
I would like to fetch it in a single command line like
snmpwalk -v2c -c community localhost 1.3.6.1.2.1.2 | grep tun0 | ?
There are so many options that don't involve using GNU grep's experimental -P option. For example given just your sample input to work off, here's one way with any sed:
$ echo "$out" | sed 's/.*\.\([0-9]\).*tun0/\1/'
4
or any awk:
$ echo "$out" | awk -F'[. ]' '/tun0/{print $2}'
4
I'd recommend pattern (?<=ifDescr\.)[^ =]+
Explanation:
(?<=ifDescr\.) - positive lookbehind, asserts that wat is preceeding is ifDescr.
[^ =]+ match one or more characters other than space or equal sign =
Demo

Bash grep ip from line

I have the file ip.txt which contain the following
ata001dcfe16f85.mm.ph.ph.cox.net (24.252.231.220)
220.231.252.24.xxx.com (24.252.231.220)
and I made this bash command to extract ips :
grep -Eo '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' ip.txt | sort -u > good.txt
I want to edit the code so it extracts the ips between the parentheses ONLY . not all the ips on the line because the current code extract the ip 220.231.252.24
To get the IP within paranthesis all you need is to wrap the entire regex in an escaped \( \)
grep -Eo '\((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\)'
will give output as
(24.252.231.220)
(24.252.231.220)
if you want to get rid of the paranthesis as well in the output, look around would be usefull
grep -oP '(?<=\()(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?=\))'
would produce output as
24.252.231.220
24.252.231.220
a much more lighter version would be
grep -oP '(?<=\()(25[0-5]|2[0-4][0-9]|[01]?[0-9]{2}?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]{2}?)){3}(?=\))'
here
[0-9]{2} matches the number 2 times
(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]{2}?)){3} matches . followed by 3 digit number three times
The repeating lines can be removed using a pipe to uniq as
grep -oP '(?<=\()(25[0-5]|2[0-4][0-9]|[01]?[0-9]{2}?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]{2}?)){3}(?=\))' input | uniq
giving the output as
24.252.231.220
You can try awk
awk -F"[()]" '{print $(NF-1)}' file
24.252.231.220
24.252.231.220

Extracting IP address from a line from ifconfig output with grep

Given this specific line pulled from ifconfig, in my case:
inet 192.168.2.13 netmask 0xffffff00 broadcast 192.168.2.255
How could one extract the 192.168.2.13 part (the local IP address), presumably with regex?
Here's one way using grep:
line='inet 192.168.2.13 netmask 0xffffff00 broadcast 192.168.2.256'
echo "$line" | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"
Results:
192.168.2.13
192.168.2.256
If you wish to select only valid addresses, you can use:
line='inet 192.168.0.255 netmask 0xffffff00 broadcast 192.168.2.256'
echo "$line" | grep -oE "\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"
Results:
192.168.0.255
Otherwise, just select the fields you want using awk, for example:
line='inet 192.168.0.255 netmask 0xffffff00 broadcast 192.168.2.256'
echo "$line" | awk -v OFS="\n" '{ print $2, $NF }'
Results:
192.168.0.255
192.168.2.256
Addendum:
Word boundaries: \b
use this regex ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?=\s*netmask)
you can use egrep (which is basically the same as grep -E)
in egrep there are named groups for character classes, e.g.: "digit"
(which makes the command longer in this case - but you get the point...)
another thing that is good to know is that you can use brackets to repeat a pattern
ifconfig | egrep '([0-9]{1,3}\.){3}[0-9]{1,3}'
or
ifconfig | egrep '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}'
if you only care about the actual IP address use the parameter -o to limit output to the matched pattern instead of the whole line:
ifconfig | egrep -o '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}'
...and if you don't want BCast addresses and such you may use this grep:
ifconfig | egrep -o 'addr:([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}' | egrep -o '[[:digit:]].*'
I assumed you were talking about IPv4 addresses only
Just to add some alternative way:
ip addr | grep -Po '(?!(inet 127.\d.\d.1))(inet \K(\d{1,3}\.){3}\d{1,3})'
it will print out all the IPs but the localhost one.
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
I don't have enough reputation points to comment, but I found a bug in Steve's "select only valid addresses" regex. I don't quite understand the problem, but I believe I have found the fix. The first command demonstrates the bug; the second one demonstrates the fix:
$ echo "test this IP: 200.1.1.1" |grep -oE "\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"
$ echo "test this IP: 200.1.1.1" |grep -oE "\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"
200.1.1.1
$
grep -oE "\b([0-9]{1,3}\.?){4}\b"
One way using sed. First instruction deletes all characters until first digit in the line, and second instruction saves first IP in group 1 (\1) and replaces all the line with it:
sed -e 's/^[^0-9]*//; s/\(\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*/\1/'
maybe this, one sed command, just for sports:
ip -o -4 addr show dev eth0 | sed 's/.* inet \([^/]*\).*/\1/'
This code works nicely and easy too.
ifconfig | grep Bcast > /tmp/ip1
cat /tmp/ip1 | awk '{ print $2 }' > /tmp/ip2
sed -i 's/addr://' /tmp/ip2
IPADDRESS=$(cat /tmp/ip2)
echo "$IPADDRESS"
This code works for me on raspberry pi zero w.
(extract wlan0: inet 192.168.x.y address from ifconfig output)
Search for pattern 'inet 192' in ifconfig output and get the 10th position using space delimiter.
$> ifconfig |grep 'inet 192'|cut -d' ' -f10
Output:
192.168.1.6
If using grep that supports Perl regex:
(your command that pulls mentioned line) | grep -Po 'inet \K[\d\.]+'

Filter out IP using regex and sed

I'm having real trouble converting my regular expression into a working sed command on Centos 5.5.
I want to filter the IP address out of a string:
"example.org has address 123.45.67.890" -> "123.45.67.890"
My regular expression so far is:
/([a-zA-Z\. ]+)([0-9\.]+)/
And an example of my command using sed is:
host example.org | grep 'has address' | sed 's/\([a-zA-Z\\. ]+\)\([0-9\\.]+\)/\2/'
But all I get back from that command is the input to sed: "example.org has address 123.45.67.890"
Any ideas?
host example.org | awk '/has address/ {print $4 }'
Here's a very simple way to do it without a regex:
host example.org | grep "has addres" | awk '{print $4}'
You don't really need sed for this. You could use cut instead to parse the spaces:
host example.org | grep 'has address' | cut -d' ' -f4
This just takes the 4th word, when delimited by spaces.
Your ([a-zA-Z\. ]+) captures everything before the IP address and includes that in the match. It will also cause matching to fail if the domain name has any numbers in it. Use a lookbehind:
/(?<has address )\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
You apparently need to use Perl mode for sed to support lookbehinds. You could also use capture groups. If you want a more discriminating pattern (i.e. only match stuff that looks very strongly like an IP address), you can try this:
/(?<has address )(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\b/
That should match four numbers from 0-255, delimited by dots and preceded by 'has address '.
Using GNU grep:
host example.org | grep -Po '.*has address \K[0-9.]*'
host exmaple.org | sed -n 's/^.* (.*)$/\1/p'