0

I am using Python3 to try to emulate

awk '/STRING/'

I made some code that works, but it stops on the first instance instead of finding all lines that contain the specified character/string.

After I made the code, I saw these two pages, but the suggestions did not work

Print line containing "word" python

Search and get a line in Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#Made by Devyn Collier Johnson, NCLA, Linux+, LPIC-1, DCTS
def cat(openfile): #Emulates cat#
    with open(openfile) as file:
        lines = file.readlines()
        return ''.join(lines)
def GETLINEWITH(FILECONTENTS, CONTAINING):
    for item in FILECONTENTS.split('\n'):
        if CONTAINING in item:
            return item.strip()

print(GETLINEWITH(cat('./Base.xaiml'), 'terminal'))

I have a file (./Base.xaiml) that contains several instances of the word "terminal". I am using this file and string for testing purposes.

EDIT: I also want to save the results to a variable -

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#Made by Devyn Collier Johnson, NCLA, Linux+, LPIC-1, DCTS
def cat(openfile): #Emulates cat#
    with open(openfile) as file:
        lines = file.readlines()
        return ''.join(lines)
def GETLINEWITH(FILECONTENTS, CONTAINING):
    for item in FILECONTENTS.split('\n'):
        if CONTAINING in item:
            print(item.strip()) #I implemented the give suggestion

VAR = GETLINEWITH(cat('./Base.xaiml'), 'terminal'))

Results:

I tried Jon Clements suggestion:

with open('./Base.xaiml') as fin:
    matching = ('terminal' in line for line in fin)
    for line in matching:
        VAR = matching
print(VAR)

However, the output is one memory address. ''.join() and group() do not help.

Edit2:

Newest code Issues - nonetype error and the output cannot be saved to a variable

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#Made by Devyn Collier Johnson, NCLA, Linux+, LPIC-1, DCTS
def cat(openfile): #Emulates cat#
    with open(openfile) as file:
        lines = file.readlines()
        return ''.join(lines)
def GETLINEWITH(FILECONTENTS, CONTAINING):
    for item in FILECONTENTS.split('\n'):
        if CONTAINING in item:
            print(item.strip())
for line in GETLINEWITH(cat('./Base.xaiml'), 'terminal'):
    print(line)
Community
  • 1
  • 1
Devyn Collier Johnson
  • 4,124
  • 3
  • 18
  • 39

3 Answers3

3

Here you go, note that I am just putting together everyone elses comments explicitly for you.

#!/usr/bin/env python3

def cat(openfile):
  with open(openfile) as file:
    return file.read()

def GETLINEWITH(FILECONTENTS, CONTAINING):
  for item in FILECONTENTS.split('\n'):
    if CONTAINING in item:
      yield item.strip()

matchedlines = []

for line in GETLINEWITH(cat('./Base.xaiml'), 'terminal'):
   print(line)
   matchedlines.append(line)

print(matchedlines)

The matchedlines variable is just an example for you of one way to save the matched lines in a variable.

An alternative GETLINEWITH implementation is:

import re

def GETLINEWITH(FILECONTENTS, CONTAINING):
  for item in FILECONTENTS.split('\n'):
    m = re.search(CONTAINING, item)
    if m:
      yield m.string

Which will let you match on regular expressions.

casey
  • 6,855
  • 1
  • 24
  • 37
1

Anyway - the reason it "stops" is because you're returning after a match....

def GETLINEWITH(FILECONTENTS, CONTAINING):
    for item in FILECONTENTS.split('\n'):
        if CONTAINING in item:
            return item.strip() # <---- returns as soon as something's found

Change it to a yield to make the function a generator and then loop over it:

for line in GETLINEWITH(cat('./Base.xaiml'), 'terminal'):
    print(line)

Ultimately, your function should just be:

with open('thefile') as fin:
    matching = (line for line in fin if 'something' in line)
    for line in matching:
        # do something

Or, put them all into a list:

lines = list(matching)
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
1

File objects are iterable, and a list comprehension can be used to filter the input.

with open('./Base.xaiml','r') as lines:
    matching_lines = [ line.rstrip('\n')
                       for line in lines
                       if line.find('terminal') != -1 ]

for line in matching_lines:
    print line         # change to print(line) for python 3.x

EDIT: or if you really want it to be a function

def matching_lines(filename, substring):
    """ Return all the lines in a file that contain a given substring. """
    with open(filename,'r') as f:
        return [s.rstrip('\n') for s in f if s.find(substring) != -1]

for s in matching_lines('./Base.xaiml', 'terminal'):
    print s
Marc Poulin
  • 81
  • 2
  • 2