Add parameters to limit replace to certain section of the file

Add parameters 'after' and 'before' to limit the replacement/remove of
lines to a certain section of the file.
pull/22739/head
Jens Carl 8 years ago committed by Brian Coca
parent 6ced1ad5a2
commit cd39ff9996

@ -58,6 +58,22 @@ options:
- The string to replace regexp matches. May contain backreferences - The string to replace regexp matches. May contain backreferences
that will get expanded with the regexp capture groups if the regexp that will get expanded with the regexp capture groups if the regexp
matches. If not set, matches are removed entirely. matches. If not set, matches are removed entirely.
after:
required: false
version_added: "2.3"
description:
- If specified, the line after the replace/remove will start. Can be used
in combination with C(before).
Uses Python regular expressions; see
U(http://docs.python.org/2/library/re.html).
before:
required: false
version_added: "2.3"
description:
- If specified, the line before the replace/remove will occur. Can be used
in combination with C(after).
Uses Python regular expressions; see
U(http://docs.python.org/2/library/re.html).
backup: backup:
required: false required: false
default: "no" default: "no"
@ -88,6 +104,31 @@ EXAMPLES = r"""
replace: '\1new.host.name\2' replace: '\1new.host.name\2'
backup: yes backup: yes
# Replace after the expression till the end of the file
- replace:
path: /etc/hosts
regexp: '(\s+)old\.host\.name(\s+.*)?$'
replace: '\1new.host.name\2'
after: 'Start after line.*'
backup: yes
# Replace before the expression till the begin of the file
- replace:
path: /etc/hosts
regexp: '(\s+)old\.host\.name(\s+.*)?$'
replace: '\1new.host.name\2'
before: 'Start before line.*'
backup: yes
# Replace between the expressions
- replace:
path: /etc/hosts
regexp: '(\s+)old\.host\.name(\s+.*)?$'
replace: '\1new.host.name\2'
after: 'Start after line.*'
before: 'Start before line.*'
backup: yes
- replace: - replace:
path: /home/jdoe/.ssh/known_hosts path: /home/jdoe/.ssh/known_hosts
regexp: '^old\.host\.name[^\n]*\n' regexp: '^old\.host\.name[^\n]*\n'
@ -130,6 +171,7 @@ def write_changes(module, contents, path):
if valid: if valid:
module.atomic_move(tmpfile, path, unsafe_writes=module.params['unsafe_writes']) module.atomic_move(tmpfile, path, unsafe_writes=module.params['unsafe_writes'])
def check_file_attrs(module, changed, message): def check_file_attrs(module, changed, message):
file_args = module.load_file_common_arguments(module.params) file_args = module.load_file_common_arguments(module.params)
@ -142,12 +184,15 @@ def check_file_attrs(module, changed, message):
return message, changed return message, changed
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
path=dict(required=True, aliases=['dest', 'destfile', 'name'], type='path'), path=dict(required=True, aliases=['dest', 'destfile', 'name'], type='path'),
regexp=dict(required=True), regexp=dict(required=True),
replace=dict(default='', type='str'), replace=dict(default='', type='str'),
after=dict(required=False),
before=dict(required=False),
backup=dict(default=False, type='bool'), backup=dict(default=False, type='bool'),
validate=dict(default=None, type='str'), validate=dict(default=None, type='str'),
), ),
@ -169,8 +214,28 @@ def main():
contents = to_text(f.read(), errors='surrogate_or_strict') contents = to_text(f.read(), errors='surrogate_or_strict')
f.close() f.close()
mre = re.compile(params['regexp'], re.MULTILINE) pattern = ''
result = re.subn(mre, params['replace'], contents, 0) if params['after']:
pattern = '%s(.*)' % params['after']
elif params['before']:
pattern = '(.*)%s' % params['before']
elif params['after'] and params['before']:
pattern = '%s(.*?)%s' % (params['before'], params['after'])
if pattern:
section_re = re.compile(pattern, re.DOTALL)
match = re.search(section_re, contents)
if match:
section = match.group(0)
mre = re.compile(params['regexp'], re.MULTILINE)
result = re.subn(mre, params['replace'], section, 0)
if result[1] > 0 and section != result[0]:
result = (contents.replace(section, result[0]), result[1])
else:
mre = re.compile(params['regexp'], re.MULTILINE)
result = re.subn(mre, params['replace'], contents, 0)
if result[1] > 0 and contents != result[0]: if result[1] > 0 and contents != result[0]:
msg = '%s replacements made' % result[1] msg = '%s replacements made' % result[1]
@ -196,5 +261,6 @@ def main():
res_args['msg'], res_args['changed'] = check_file_attrs(module, changed, msg) res_args['msg'], res_args['changed'] = check_file_attrs(module, changed, msg)
module.exit_json(**res_args) module.exit_json(**res_args)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

Loading…
Cancel
Save