0

I would like to capture some characters following a word in a string. For example,

Pinging 10.1.1.1 with 32 bytes of data:

Reply from 10.1.1.1: bytes=32 time=39ms TTL=253

Reply from 10.1.1.1: bytes=32 time=17ms TTL=253

Reply from 10.1.1.1: bytes=32 time=17ms TTL=253 

Reply from 10.1.1.1: bytes=32 time=17ms TTL=253

Ping statistics for 10.1.1.1:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds:
    Minimum = 17ms, Maximum = 39ms, Average = 22ms

I would like to get characters following time= but stopping the space before TTL for the first instance of time=

I know I can do a split to time= and get the characters which follow but I don't know how to have it stop before the TTL (the number could be more than 2 digits for instance, so just getting the 4 which follow isn't an option)

Perhaps regex would also be an option? I've seen something like (?:time=).* would get the first instance but, again, i'm uncertain how to specify it to stop after the ms.

Edit - Added final code now that it is working. Thanks for all the help!

import os
import subprocess
import re

#Define Target
hostname = raw_input("Enter IP: ") 

#Run ping and return output to stdout.
#subprocess.Popen runs cmdline ping, pipes the output to stdout. .stdout.read() then reads that stream data and assigns it to the ping_response variable
ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read()

word = "Received = 1"



latency = 1

p = re.compile(ur'(?<=time)\S+')
x = re.findall(p, ping_response)

if word in ping_response:
print "Online with latency of "+x[0]

else:
print "Offline"

4
  • how are you running the ping? Commented May 1, 2015 at 17:56
  • @PadraicCunningham I added the code I am using to the question. Thanks! Commented May 1, 2015 at 18:01
  • @PadraicCunningham Yes. Commented May 1, 2015 at 18:14
  • Ok, was going to say you could grep the output, since it is windows an easier way would be to simply use check_output Commented May 1, 2015 at 18:14

3 Answers 3

4

Try this RegEx

(?<=time=)\S+

This should do it with re.findall for you.

See demo here

import re
p = re.compile(ur'(?<=time=)\S+')
test_str = u"\n\n Pinging 10.1.1.1 with 32 bytes of data:\n\n Reply from 10.1.1.1: bytes=32 time=39ms TTL=253\n\n Reply from 10.1.1.1: bytes=32 time=17ms TTL=253\n\n Reply from 10.1.1.1: bytes=32 time=17ms TTL=253\n\n Reply from 10.1.1.1: bytes=32 time=17ms TTL=253\n\n Ping statistics for 10.1.1.1: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 17ms, Maximum = 39ms, Average = 22ms\n"     
re.findall(p, test_str)
Sign up to request clarification or add additional context in comments.

6 Comments

@BhargavRao hi!!!!!!!!!! yups!!!! long trip :P........ stackoverflow.com/questions/29988595/… see dis!!!!!!! brilliant answer by Anti happala.......There's always something to learn from SO !!!!!!!!
If I have my sample string (the one starting with "Pinging") in a variable called ping_response, for the line where you start [test_str = u"\n\n ..."] would I just put [test_str = u ping_response] ?
How do I then output that data? I have {p = re.compile(ur'(?<=time=)\S+') re.findall(p, ping_response) if word in ping_response: print "Online with latency of %s" % ?????}
@Abraxas use x=re.findall(p, test_str) x will be list of all times
@Abraxas (?<=time[<=])\S+
|
1

Use a regexp but keep it simple: Instead of lookaheads/lookbehinds, do it the old-fashioned way with capturing groups:

>>> times = re.findall(r"time=(.*?) ", pingdata)
>>> times
['39ms', '17ms', '17ms', '17ms']

Explanation: .*? is a non-greedy regular expression, so it will stop as soon as a space matches after the parens. That matches exactly what you want. re.findall() with a capturing expression will return what matches inside the parens, not the entire match.

If you only want the first match (as you say in your question, I now notice), take times[0] or use re.search instead, which returns the first match (but as a match object, so you extract the captured group).

>>> m = re.search(r"time=(.*?) ", pingdata)
>>> m.group(1)
'39ms'

8 Comments

As I am very new to this could I verify that 'pingdata' is the variable my string of the ping response is and then clarify how I would present this number in my response (ie: [print "Online with latency of %s" % latency] would latency = m.group(1)?
Yes, pingdata is a string containing the entire ping response. m.group(1) is also a string, so you can use it as you suggest (or simply "Online with latency "+m.group(1))
You are welcome. PS. If you're just getting started, I suggest upgrading to python 3. It's very mature and well-supported by now, there's no reason to work with python 2 unless you have no choice for some reason.
I am a little bit of the way in to Zed Shaw's book "Learn Python the Hard Way" and he actually said the opposite but I am glad to hear a differing opinion. I'm just hoping to become competent with some scripting and programming to aid in my sysadmin work. I'll definitely be taking a look! Thanks again
When was the book written? It took a while for various third-party libraries to convert to python 3, but the dust has settled pretty well by now. Already there are plenty of things in python 3 that python 2 lacks. And if you expect to be doing anything with non-English text, you should absolutely, definitely switch.
|
0
test = 'Reply from 10.1.1.1: bytes=32 time=39ms TTL=253'
test.split()[4].split('=')[1]

Step by step:

test.split()
['Reply', 'from', '10.1.1.1:', 'bytes=32', 'time=39ms', 'TTL=253']
test.split()[4].split('=')
'time=39ms'
test.split()[4].split('=')
['time', '39ms']
test.split()[4].split('=')[1]
'39ms'

Output:

#1 '39ms'

Another test:

test = 'Reply from 10.1.1.1: bytes=32 time=38833434343434349ms TTL=253'
test.split()[4].split('=')[1]
'38833434343434349ms'

7 Comments

I don't think this would work, the time value could be something like 2940ms or 374ms so it's not always going to be 5 characters
It will work. .split()[4] gets the 5th element of the list that was created after you split the string. It can be on length n
Ohh, okay, that makes sense, i didn't realize it was splitting the string by spaces and looking at each substring as an element. Thanks!
what about the other lines in the output?
@PadraicCunningham -This is Assuming the OP is using only a single string at a time.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.