Skip to content

Instantly share code, notes, and snippets.

@aorzh
Created February 25, 2020 16:59
Show Gist options
  • Save aorzh/8fc575be53d2ecac6f4be94cca9e127c to your computer and use it in GitHub Desktop.
Save aorzh/8fc575be53d2ecac6f4be94cca9e127c to your computer and use it in GitHub Desktop.
bulk replace
task description:
please, write a function that receives
1)path to file
2) string to replace
3) the new string to replace with
4) in which line in the file to replace (if empty, then replace all)
I assume new string should not be same with pattern
Line number it's a real number (starts from 1). For example client see in text editor this number and pass it to func. I
will switch it to index (as it's starts from 0)
I wrapped it's to try/except with custom exception because in this way exceptions more clear and I can manage it.
I added helper function for write lines because do not necessary write same code twice.
There also possible to use fileinput standard library (https://docs.python.org/3/library/fileinput.html).
But as multiple files wasn't in requirements I used open() as docs said "If you just want to read or write one file
see open()."
import unittest
from util import bulk_replace, UtilException
class UtilTestCases(unittest.TestCase):
def setUp(self):
self.filepath = 'test_text'
self.pattern = 'foo'
self.replace_with = 'bar'
def test_same_patterns(self):
try:
bulk_replace(filepath=self.filepath, pattern=self.pattern, replace_with='foo')
except UtilException as e:
self.assertEqual(e.__str__(), 'pattern and replace_with can not be same')
def test_line(self):
try:
bulk_replace(filepath=self.filepath, pattern=self.pattern, replace_with=self.replace_with, line=999)
except UtilException as e:
self.assertEqual(e.__str__(), 'line not found')
try:
bulk_replace(filepath=self.filepath, pattern=self.pattern, replace_with=self.replace_with, line=-1)
except UtilException as e:
self.assertEqual(e.__str__(), 'line index should be gte 1')
def test_replace_one_line(self):
bulk_replace(filepath=self.filepath, pattern=self.pattern, replace_with=self.replace_with, line=1)
file = open(self.filepath, 'r')
line = file.readlines()
file.close()
self.assertEqual(line[0].strip('\n'), self.replace_with)
# switch it back
bulk_replace(filepath=self.filepath, pattern=self.replace_with, replace_with=self.pattern, line=1)
def test_replace_all(self):
file = open(self.filepath, 'r')
old = file.readlines()
file.close()
bulk_replace(filepath=self.filepath, pattern=self.pattern, replace_with=self.replace_with)
file = open(self.filepath, 'r')
lines = file.readlines()
self.assertTrue(self.pattern not in lines)
# switch it back
file = open(self.filepath, 'w')
file.writelines(old)
file.close()
if __name__ == '__main__':
unittest.main()
foo
bar
foo-bar
bar-foo-bar
foo-bar-bar
class UtilException(Exception):
pass
def bulk_replace(filepath, pattern, replace_with, line=None):
"""
Function which open file, find necessary pattern and replace it with new fragment.
:param filepath: Path to file
:param pattern: String to replace
:param replace_with: The new string to replace with
:param line: In which line in the file to replace (if empty, then replace all)
:return:
"""
try:
assert pattern != replace_with
except AssertionError:
raise UtilException('pattern and replace_with can not be same')
with open(filepath, 'r') as f:
text = f.readlines()
f.close()
if line: # assume we get line number, not index
try:
assert line >= 1
try:
# replace necessary text
text[line-1] = text[line-1].replace(pattern, replace_with)
_write_lines(filepath, text)
except IndexError:
raise UtilException('line not found')
except AssertionError:
raise UtilException('line index should be gte 1')
else:
# walk through all lines and replace necessary text
lines = [line.replace(pattern, replace_with) for line in text]
_write_lines(filepath, lines)
def _write_lines(filepath, lines):
"""
Helper function
:param filepath: File path to open
:param lines: list of lines
:return:
"""
with open(filepath, 'w') as f:
f.writelines(lines)
f.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment