Writing a line in a file when finding a keyword - python

I am trying to make a function which writes a line when it finds some text inside a file.
Example: it finds "hello" in a .txt file so then writes "Hi!" in the following line. There is something else, i want it to write "Hi!" not the first time it finds "hello" but the second.
Here is what i have been trying, but i don't know if the idea is right. Any help?
def line_replace(namefilein):
print namefilein
filein=open(namefilein, "rw")
tag="intro"
filein.read()
for line in filein:
if tag=="second" or tag=="coord":
try:
filein.write("\n\n %s" %(text-to-be-added))
print line
except:
if tag=="coord":
tag="end"
else:
tag="coord"
if " text-to-find" in line:
if tag=="intro":
tag="first"
elif tag=="first":
tag="second"
filein.close()

You can use this code:
def line_replace(namefilein):
new_content = ''
first_time = False
with open(namefilein, 'r') as f:
for line in f:
new_content += line
if 'hello' in line:
if first_time:
new_content += 'Hi!' + '\n'
else:
first_time = True
with open(namefilein, 'w') as f:
f.write(new_content)
Look that I am using the with statement that in Python is a context manager, so it means, in this case, when the block of code has executed, then the file will be closed automatically.
Let's supposed you have a file my_file.txt which contents is:
hello
friend
this
is
hello
And let's say your file is in the same directory than the python file that has your code, so calling:
line_replace('my_file.txt')
will produce the following output:
hello
friend
hello
Hi!
is

Related

Unable to move to second function after the result of the first

Program Goal: Search a defined yamlfile (scan_dcn.yaml) and return all lines matching the search criteria as defined in the function_search_search_key() and function_search_event_type() functions.
Input File - scan_dcn.yaml:
search_dict:
[
{search_key: ["Failed to Process the file"],
event_type: "evttyp_repl_dcn_error",
event_description: "Failure to process DCN file",
priority: 50,
scan_interval: 1,
remove_dups: True,
category: "dcn",
context_begin: 0,
context_end: 1,
reportable: False,
offset: 0
},
Problem:
My program will return function_search_search_key() but will not proceed to function_search_event_type().
I would think that my problem is that I have no logic to proceed to the second function after the completion of the first.
Do I need to return a value in each function to proceed?
Python Source Code
yamlfile = open('scan_dcn.yaml', 'r')
def function_search_search_key():
search_search_key = ['{search_key:']
for line in yamlfile.readlines():
for word in search_search_key:
if word in line:
print(line)
def function_search_event_type():
search_event_type = ['event_type:']
for line in yamlfile.readlines():
for word in search_event_type:
if word in line:
print(line)
def main():
function_search_search_key()
function_search_event_type()
main()
In your first function you read the whole file with readlines. When you use readlines again in your second function you're already at the end of the file and there is no more data to read, so the for loop is not even entered.
But there's no need to read the file again for every function. Read the file outside of the functions and put it in a list. Then add a parameter to each of those functions that takes this list. In the function you can loop over the list.
def function_search_search_key(lines):
search_search_key = ['{search_key:']
for line in lines:
for word in search_search_key:
if word in line:
print(line)
def function_search_event_type(lines):
search_event_type = ['event_type:']
for line in lines:
for word in search_event_type:
if word in line:
print(line)
def main():
with open('scan_dcn.yaml', 'r') as yamlfile:
lines = yamlfile.readlines()
function_search_search_key(lines)
function_search_event_type(lines)
if __name__ = '__main__':
main()
If you ever need to change the name of the file you can do it in one place. If you open and read the file in every single function you would have to change all occurrances of the file name.
Your second function is being entered. It must if the call above it has finished.
You aren't seeing anything printed because you're attempting to loop though the same file more than once. Once you've read the file, it's exhausted. You can just re-read the file as a simple fix:
def function_search_search_key():
with open('scan_dcn.yaml', 'r') as yamlfile:
search_search_key = ['{search_key:']
for line in yamlfile.readlines():
for word in search_search_key:
if word in line:
print(line)
def function_search_event_type():
with open('scan_dcn.yaml', 'r') as yamlfile: # Read the file again
search_event_type = ['event_type:']
for line in yamlfile.readlines():
for word in search_event_type:
if word in line:
print(line)
You can read a file descriptor only once (if you don't seek to start), so you may open your file in each function
def function_search_search_key():
search_search_key = ['{search_key:']
with open('scan_dcn.yaml') as fic:
for line in fic:
for word in search_search_key:
if word in line:
print(line)
def function_search_event_type():
search_event_type = ['event_type:']
with open('scan_dcn.yaml') as fic:
for line in fic:
for word in search_event_type:
if word in line:
print(line)

Why is my function appending the file name string instead of the lines of the file itself?

I am trying to append the lines of a file (.py file) to a list as a way to count the lines and figure out which lines are code using a conditional statement. The problem is that my function that I created is reading the 'file name' instead of the lines of the file itself. Where did I go wrong with this. I am surprised I got this far...it works, but not for the right reason.
from tkinter.filedialog import askopenfilename
import time
def getFileName():
sourceCode = askopenfilename() # Opens dialog box to locate and select file
return sourceCode
def scLines():
scList = []
sourceCode = getFileName()
for line in sourceCode:
if line[0] != "#" or line != "":
scList.append(line)
return scList
def countscLine():
lineCount = len(scLines())
return lineCount
def fCount():
fList = []
sourceCode = getFileName()
for line in sourceCode:
if line[0:3] == 'def ':
fAmout.append(line)
lineCount = len(fList)
return fList
# Get file name from user
def main():
print("Select the file to be analyzed")
time.sleep(5) # Waits 5 seconds before initiating function
sourceCode = getFileName()
print("The file is", sourceCode)
print("The source code has ", countscLine(), "lines of code, and", fCount(), "functions.")
print(scLines())
print("")
main()
The problem is for line in sourceCode:. You need to actually open the file.
with open(sourceCode) as f:
for line in f:
if line[0] != "#" or line != "":
scList.append(line)
I'd recommend renaming some of your variables to be more clear as to what they actually do. For example, I would call sourceCode sourceCodefn or similar to indicate that it is a file name.

Reading a textfile into a String

I'm just starting to learn python and have a textfile that looks like this:
Hello
World
Hello
World
And I want to add the numbers '55' to the beggining and end of every string that starts with 'hello'
The numbers '66' to the beggining and every of every string that starts with 'World'
etc
So my final file should look like this:
55Hello55
66World66
55Hello55
66World66
I'm reading the file in all at once, storing it in a string, and then trying to append accordingly
fp = open("test.txt","r")
strHolder = fp.read()
print(strHolder)
if 'Hello' in strHolder:
strHolder = '55' + strHolder + '55'
if 'World' in strHolder:
strHolder = '66' + strHolder + '66'
print(strHolder)
fp.close()
However, my string values '55' and '66' are always being added to the front of the file and end of the file, not the front of a certain string and to the end of the string, where I get this output of the string:
6655Hello
World
Hello
World
5566
Any help would be much appreciated.
You are reading the whole file at once with .read().
You can read it line by line in a for loop.
new_file = []
fp = open("test.txt", "r")
for line in fp:
line = line.rstrip("\n") # The string ends in a newline
# str.rstrip("\n") removes newlines at the end
if "Hello" in line:
line = "55" + line + "55"
if "World" in line:
line = "66" + line + "66"
new_file.append(line)
fp.close()
new_file = "\n".join(new_file)
print(new_file)
You could do it all at once, by reading the whole file and splitting by "\n" (newline)
new_file = []
fp = open("text.txt")
fp_read = fp.read()
fp.close()
for line in fp_read.split("\n"):
if "Hello" # ...
but this would load the whole file into memory at once, while the for loop only loads line by line (So this may not work for larger files).
The behaviour of this is that if the line has "Hello" in it, it will get "55" before and after it (even if the line is " sieohfoiHellosdf ") and the same for "World", and if it has both "Hello" and "World" (e.g. "Hello, World!" or "asdifhoasdfhHellosdjfhsodWorldosadh") it will get "6655" before and after it.
Just as a side note: You should use with to open a file as it makes sure that the file is closed later.
new_file = []
with open("test.txt") as fp: # "r" mode is default
for line in fp:
line = line.rstrip("\n")
if "Hello" in line:
line = "55" + line + "55"
if "World" in line:
line = "66" + line + "66"
new_file.append(line)
new_file = "\n".join(new_file)
print(new_file)
You need to iterate over each line of the file in order to get the desired result. In your code you are using .read(), instead use .readlines() to get list of all lines.
Below is the sample code:
lines = []
with open("test.txt", "r") as f:
for line in f.readlines(): # < Iterate over each line
if line.startswith("Hello"): # <-- check if line starts with "Hello"
line = "55{}55".format(line)
elif line.startswith("World"):
line = "66{}66".format(line)
lines.append(line)
print "\n".join(lines)
Why to use with? Check Python doc:
The ‘with‘ statement clarifies code that previously would use try...finally blocks to ensure that clean-up code is executed. In this section, I’ll discuss the statement as it will commonly be used. In the next section, I’ll examine the implementation details and show how to write objects for use with this statement.
The ‘with‘ statement is a control-flow structure whose basic structure is:
with expression [as variable]: with-block
The expression is evaluated, and it should result in an object that supports the context management protocol (that is, has enter() and exit() methods).
once you have read the file:
read_file = read_file.replace('hello','55hello55')
It'll replace all hellos with 55hello55
and use with open(text.txt, 'r' ) as file_hndler:
To read a text file, I recommend the following way which is compatible with Python 2 & 3:
import io
with io.open("test", mode="r", encoding="utf8") as fd:
...
Here, I make the assumption that your file use uft8 encoding.
Using a with statement make sure the file is closed at the end of reading even if a error occurs (an exception). To learn more about context manager, take a look at the Context Library.
There are several ways to read a text file:
read the whole file with: fd.read(), or
read line by line with a loop: for line in fd.
If you read the whole file, you'll need to split the lines (see str.splitlines. Here are the two solutions:
with io.open("test", mode="r", encoding="utf8") as fd:
content = fd.read()
for line in content.splilines():
if "Hello" in line:
print("55" + line + "55")
if "World" in line:
print("66" + line + "66")
Or
with io.open("test", mode="r", encoding="utf8") as fd:
for line in content.splilines():
line = line[:-1]
if "Hello" in line:
print("55" + line + "55")
if "World" in line:
print("66" + line + "66")
If you need to write the result in another file you can open the output file in write mode and use print(thing, file=out) as follow:
with io.open("test", mode="r", encoding="utf8") as fd:
with io.open("test", mode="w", encoding="utf8") as out:
for line in content.splilines():
line = line[:-1]
if "Hello" in line:
print("55" + line + "55", file=out)
if "World" in line:
print("66" + line + "66", file=out)
If you use Python 2, you'll need the following directive to use the print function:
from __future__ import print_function

How to interact with notepad document correctly in python?

I created a notepad text document called "connections.txt". I need to have some initial information inside it, several lines of just URLs. Each URL has it's own line. I put that in manually. Then in my program I have a function that checks if a URL is in the file:
def checkfile(string):
datafile = file(f)
for line in datafile:
if string in line:
return True
return False
where f is declared at the beginning of the program:
f = "D:\connections.txt"
Then I tried to write to the document like this:
file = open(f, "w")
if checkfile(user) == False:
usernames.append(user)
file.write("\n")
file.write(user)
file.close()
but it hasn't really been working correctly..I'm not sure what's wrong..am I doing it wrong?
I want the information in the notepad document to stay there ACROSS runs of the program. I want it to build up.
Thanks.
EDIT: I found something wrong... It needs to be file = f, not datafile = file(f)
But the problem is... It clears the text document every time I rerun the program.
f = "D:\connections.txt"
usernames = []
def checkfile(string):
file = f
for line in file:
if string in line:
return True
print "True"
return False
print "False"
file = open(f, "w")
user = "aasdf"
if checkfile(user) == False:
usernames.append(user)
file.write("\n")
file.write(user)
file.close()
I was working with the file command incorrectly...here is the code that works.
f = "D:\connections.txt"
usernames = []
def checkfile(string):
datafile = file(f)
for line in datafile:
if string in line:
print "True"
return True
print "False"
return False
user = "asdf"
if checkfile(user) == False:
usernames.append(user)
with open(f, "a") as myfile:
myfile.write("\n")
myfile.write(user)
The code that checks for a specific URL is ok!
If the problem is not erasing everything:
To write to the document without erasing everything you have to use the .seek() method:
file = open("D:\connections.txt", "w")
# The .seek() method sets the cursor to the wanted position
# seek(offset, [whence]) where:
# offset = 2 is relative to the end of file
# read more here: http://docs.python.org/2/library/stdtypes.html?highlight=seek#file.seek
file.seek(2)
file.write("*The URL you want to write*")
Implemented on your code will be something like:
def checkfile(URL):
# your own function as it is...
if checkfile(URL) == False:
file = open("D:\connections.txt", "w")
file.seek(2)
file.write(URL)
file.close()

How to convert this sed command to Python script?

I have one old shell script which include sed command as below.
The source data($Tmp) is a HTML table.
sed '/<table border/,/table>/d' $Tmp > $Out
Can someone help me to convert this command to Python script?
I really can't figure out how to do that with regular expression.
Many thanks..
Here's a simple implementation.
Briefly, it opens the file, iterates line by line and prints each line to the output. If it matches "<table border", delete flag set to True and following lines aren't printed to the output until it matches "table>".
import sys
f = open(sys.argv[1])
delete = False
for line in f:
if delete == False:
if "<table border" in line:
delete = True
if delete == False:
print line,
if delete == True:
if "table>" in line:
delete = False
The script copys all lines from the input file to the output file, unless it finds a line containing <table border, then it deletes all lines until it finds /table> and continues writing all further lines.
So one possibility would be:
with open('in') as inf, open('out', 'w') as outf:
while True:
line = inf.readline()
if '<table border' in line:
while True:
line = inf.readline()
if not line or '/table>' in line:
line = inf.readline()
break
if not line:
break
outf.write(line)
import sys
with open(sys.argv[1]) as f:
for line in f:
if '<table border' in line:
for line in f:
if 'table>' in line:
break
else:
sys.stdout.write(line)

Categories