Skip to content

Instantly share code, notes, and snippets.

@hughdbrown
Last active May 11, 2018 15:50
Show Gist options
  • Save hughdbrown/6042b01c9561d7fa2351aa9d3a5501a5 to your computer and use it in GitHub Desktop.
Save hughdbrown/6042b01c9561d7fa2351aa9d3a5501a5 to your computer and use it in GitHub Desktop.
Apply a set of changes in grep -n format to a file
"""
Given a set of file names, line numbers, and lines of text in `grep -n` format,
update the file with altered text.
Suppose you have added a bunch of lines of code to your code base that have double
quotes when it is your company practice to use single quotes. When you are cleaning
up your code for a pull-request, you find all the changes with double quotes,
drop extraneous lines, change all the double quotes to single quotes in the
grep output, and use this python code to apply changes to your files.
Sort of like this:
```
$ grep -n '"' $(git diff --name-only HEAD~2 | grep -v '.csv') > a
$ sed -i -e '/"""/d' a
$ sed -i "s/\"/'/g" a
$ python apply_grep_script.py a
```
"""
from itertools import groupby
import re
from operator import itemgetter
line_re = re.compile(r"""
^(?P<filename>[^:]+)
:
(?P<lineno>[^:]+)
:
(?P<rest>.*)$
""", re.VERBOSE)
def main(script):
with open(script) as handle:
lines = [line.rstrip() for line in handle]
matches = (line_re.match(line) for line in lines)
groupdict_iter = (
m.groupdict()
for m in matches
)
actions = [
(g['filename'], int(g['lineno']) - 1, g['rest'])
for g in groupdict_iter
]
for k, g in groupby(actions, itemgetter(0)):
# Read file
with open(k) as handle:
lines = [line.rstrip() for line in handle]
print("Processing {0}: {1} lines".format(k, len(lines)))
# Perform replacements
for _, lineno, replacement in g:
lines[lineno] = replacement
# Write file
with open(k, "w") as handle:
handle.write("\n".join(lines) + "\n")
if __name__ == '__main__':
import sys
for script in sys.argv[1:]:
main(script)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment