views:

4859

answers:

8

Hello

I have a simple python code that searches a files for a string "path=c:\path" ( "c:\path" is the part that can change and returns a text after "path=". Current code sketch is:

def findPath( i_file) :
  lines = open( i_file ).readlines()
  for line in lines :
    if line.startswith( "Path=" ) :
      return # what to do here in order to get line content after "Path=" ?

What is a simple way to get a string text after "Path="? Is it some simple way exists, without closures, reflection and other esoteric things ?

+2  A: 

The simplest way I can think of is with slicing-

def findPath( i_file): 
    lines = open( i_file ).readlines() 
    for line in lines: 
        if line.startswith( "Path=" ) : 
            return line[5:]

A quick note on slice notation, it uses two indices instead of the usual one. The first index indicates the first element of the sequence you want to include in the slice and the last index is the index immediately after the last element you wish to include in the slice.
Eg:

sequenceObj[firstIndex:lastIndex]

The slice consists of all the elements between firstIndex and lastIndex, including firstIndex and not lastIndex. If the first index is omitted, it defaults to the start of the sequence. If the last index is omitted, it includes all elements upto the lsdt element in the sequence. Negative indices are also allowed. Use Google to learn more about the topic.

batbrat
+1  A: 
line[5:]

gives you characters after the first five.

Steven Huwig
+2  A: 

line[5:] will give the substring you want. Search the introduction and look for 'slice notation'

Pete Kirkham
+11  A: 

Either (if the string is fixed) you can simply us

if line.startswith("Path="):
    return line[5:]

which gives you everything from position 5 on in the string (a string is also a sequence so these sequence operators work here, too).

Or you can split the line at the first =:

if "=" in line:
    param, value = line.split("=",1)

Then param is "Path" and value is the rest after the first =.

MrTopf
+1 for the split method, avoids the slight ugliness of the manual slicing on len(prefix).
bobince
But also throws if your input isn't all in the form "something=somethingelse".
Dan Olson
That's why I put the condition in front so it's only used if a "=" is in the string. Otherwise you can also test for the length of the result of split() and if it's ==2.
MrTopf
A: 

For slicing (conditional or non-conditional) in general I prefer what a colleague suggested recently; Use replacement with an empty string. Easier to read the code, less code (sometimes) and less risk of specifying the wrong number of characters. Ok; I do not use Python, but in other languages I do prefer this approach:

rightMost = fullPath.replace('Path=','',1)

or - to follow up to the first comment to this post - if this should only be done if the line starts with Path:

rightmost = re.compile('^Path=').sub('',fullPath)

The main difference to some of what has been suggested above is that there is no "magic number" (5) involved, nor any need to specify both '5' and the string 'Path=', In other words I prefer this approach from a code maintenance point of view.

fredarin
It doesn't work: 'c=Path=a'.replace("Path=", "", 1) -> 'c=a'.
J.F. Sebastian
+1  A: 
>>> import re

>>> p = re.compile(r'path=(.*)', re.IGNORECASE)

>>> path = "path=c:\path"

>>> re.match(p, path).group(1)
'c:\\path'
Selinap
1. Use `r''` strings for Windows paths. 2. `re.match()` may return None
J.F. Sebastian
+6  A: 

Remove prefix from a string

# ...
if line.startswith(prefix):
   return line[len(prefix):]

Split on the first occurrence of the separator via str.partition()

def findvar(filename, varname="Path", sep="=") :
    for line in open(filename):
        if line.startswith(varname + sep):
           head, sep_, tail = line.partition(sep) # instead of `str.split()`
           assert head == varname
           assert sep_ == sep
           return tail

Parse INI-like file with ConfigParser

from ConfigParser import SafeConfigParser
config = SafeConfigParser()
config.read(filename) # requires section headers to be present

path = config.get(section, 'path', raw=1) # case-insensitive, no interpolation

Other options

J.F. Sebastian
+1 for using configparser.
nosklo
A: 

If you know list comprehensions:

lines = [line[5:] for line in file.readlines() if line[:5] == "Path="]
Matthew Schinckel