Saya membutuhkan sesuatu yang akan memberikan opsi lari-kering dan akan bekerja secara rekursif dengan bola, dan setelah mencoba melakukannya dengan awk
dan sed
saya menyerah dan bukannya melakukannya dengan python.
The Script mencari rekursif semua file yang cocok dengan pola glob (misalnya --glob="*.html"
) untuk regex dan menggantikan dengan regex pengganti:
find_replace.py [--dir=my_folder] \
--search-regex=<search_regex> \
--replace-regex=<replace_regex> \
--glob=[glob_pattern] \
--dry-run
Setiap opsi panjang seperti --search-regex
memiliki opsi pendek yang sesuai, yaitu -s
. Jalankan dengan -h
untuk melihat semua opsi.
Misalnya, ini akan membalik semua tanggal dari 2017-12-31
ke 31-12-2017
:
python replace.py --glob=myfile.txt \
--search-regex="(\d{4})-(\d{2})-(\d{2})" \
--replace-regex="\3-\2-\1" \
--dry-run --verbose
import os
import fnmatch
import sys
import shutil
import re
import argparse
def find_replace(cfg):
search_pattern = re.compile(cfg.search_regex)
if cfg.dry_run:
print('THIS IS A DRY RUN -- NO FILES WILL BE CHANGED!')
for path, dirs, files in os.walk(os.path.abspath(cfg.dir)):
for filename in fnmatch.filter(files, cfg.glob):
if cfg.print_parent_folder:
pardir = os.path.normpath(os.path.join(path, '..'))
pardir = os.path.split(pardir)[-1]
print('[%s]' % pardir)
filepath = os.path.join(path, filename)
# backup original file
if cfg.create_backup:
backup_path = filepath + '.bak'
while os.path.exists(backup_path):
backup_path += '.bak'
print('DBG: creating backup', backup_path)
shutil.copyfile(filepath, backup_path)
with open(filepath) as f:
old_text = f.read()
all_matches = search_pattern.findall(old_text)
if all_matches:
print('Found {} matches in file {}'.format(len(all_matches), filename))
new_text = search_pattern.sub(cfg.replace_regex, old_text)
if not cfg.dry_run:
with open(filepath, "w") as f:
print('DBG: replacing in file', filepath)
f.write(new_text)
else:
for idx, matches in enumerate(all_matches):
print("Match #{}: {}".format(idx, matches))
print("NEW TEXT:\n{}".format(new_text))
elif cfg.verbose:
print('File {} does not contain search regex "{}"'.format(filename, cfg.search_regex))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='''DESCRIPTION:
Find and replace recursively from the given folder using regular expressions''',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='''USAGE:
{0} -d [my_folder] -s <search_regex> -r <replace_regex> -g [glob_pattern]
'''.format(os.path.basename(sys.argv[0])))
parser.add_argument('--dir', '-d',
help='folder to search in; by default current folder',
default='.')
parser.add_argument('--search-regex', '-s',
help='search regex',
required=True)
parser.add_argument('--replace-regex', '-r',
help='replacement regex',
required=True)
parser.add_argument('--glob', '-g',
help='glob pattern, i.e. *.html',
default="*.*")
parser.add_argument('--dry-run', '-dr',
action='store_true',
help="don't replace anything just show what is going to be done",
default=False)
parser.add_argument('--create-backup', '-b',
action='store_true',
help='Create backup files',
default=False)
parser.add_argument('--verbose', '-v',
action='store_true',
help="Show files which don't match the search regex",
default=False)
parser.add_argument('--print-parent-folder', '-p',
action='store_true',
help="Show the parent info for debug",
default=False)
config = parser.parse_args(sys.argv[1:])
find_replace(config)
Here
adalah versi terbaru dari skrip yang menyoroti istilah pencarian dan penggantian dengan warna yang berbeda.