{"id":25410116,"url":"https://github.com/msztolcman/subst","last_synced_at":"2025-12-14T00:07:41.776Z","repository":{"id":6654115,"uuid":"7898548","full_name":"msztolcman/subst","owner":"msztolcman","description":"Search and des... argh... replace in many files at once. Use regexp and power of Python to replace what you want.","archived":false,"fork":false,"pushed_at":"2022-12-26T20:35:54.000Z","size":169,"stargazers_count":20,"open_issues_count":5,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-24T15:23:49.542Z","etag":null,"topics":["ed","python","regex","regexp","replace","search","sed","substitute","text","utf8"],"latest_commit_sha":null,"homepage":"https://msztolcman.github.io/subst/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/msztolcman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-01-29T18:42:47.000Z","updated_at":"2021-08-07T07:39:43.000Z","dependencies_parsed_at":"2023-01-13T14:04:06.528Z","dependency_job_id":null,"html_url":"https://github.com/msztolcman/subst","commit_stats":null,"previous_names":["mysz/subst"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msztolcman%2Fsubst","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msztolcman%2Fsubst/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msztolcman%2Fsubst/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msztolcman%2Fsubst/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/msztolcman","download_url":"https://codeload.github.com/msztolcman/subst/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239114257,"owners_count":19583985,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ed","python","regex","regexp","replace","search","sed","substitute","text","utf8"],"created_at":"2025-02-16T09:30:19.329Z","updated_at":"2025-10-31T04:32:01.355Z","avatar_url":"https://github.com/msztolcman.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"subst\n=====\n\n[![subst version](https://img.shields.io/pypi/v/subst.svg)](https://pypi.python.org/pypi/subst)\n[![subst license](https://img.shields.io/pypi/l/subst.svg)](https://pypi.python.org/pypi/subst)\n[![subst python compatibility](https://img.shields.io/pypi/pyversions/subst.svg)](https://pypi.python.org/pypi/subst)\n[![say thanks!](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/msztolcman)\n\n`subst` is simple utility to replace one string (or expression) into another\nin given list of files.\n\nIf you like this tool, just [say thanks](https://saythanks.io/to/msztolcman).\n\nCurrent stable version\n----------------------\n\n0.4.0\n\nBut why?\n--------\n\n1. There is `sed` for example?\n\n    Yes, it is. But `sed` use regexps engine called \"Basic Regular Expressions\", or \"Extended\n    Regular Expression\". PCRE (Perl Compatible Regular Expressions) used by `subst` is much\n    more widely used engine.\n\n2. So I can use Perl!\n\n    Of course you can. But not everyone know how to use Perl. I know, but `subst` is IMHO\n    simpler to use.\n\nOK, so how to use it?\n---------------------\n\nSimple usage\n------------\n\n    echo 'Hello World!' | subst -s 's/Hello/Hi/' -\n\nor:\n\n    subst -p '(192\\.168)\\.1\\.(10)' -r '\\1.0.\\2' /etc/hosts\n\nMore\n----\n\nEverything is in help :) Just execute:\n\n    subst --help\n\nLook at result:\n\n    % subst --help\n    usage: subst.py [-h] [-p PATTERN] [-r REPLACE] [--eval-replace] [-t]\n                    [-s \"s/PAT/REP/gixsm\"] [-c COUNT] [-l] [-i]\n                    [--pattern-dot-all] [--pattern-verbose] [--pattern-multiline]\n                    [-u] [--encoding-input ENCODING_INPUT]\n                    [--encoding-file ENCODING_FILE]\n                    [--encoding-filesystem ENCODING_FILESYSTEM] [-b] [-e EXT] [-W]\n                    [--stdin] [--stdout] [-V] [--debug] [-v]\n                    [files [files ...]]\n    \n    Replace PATTERN with REPLACE in many files.\n    \n    positional arguments:\n    files                 files to parse\n    \n    optional arguments:\n    -h, --help            show this help message and exit\n    -p PATTERN, --pattern PATTERN\n                            pattern to replace for. Supersede --pattern-and-\n                            replace. Required if --replace is specified.\n    -r REPLACE, --replace REPLACE\n                            replacement. Supersede --pattern-and-replace. Required\n                            if --pattern is specified.\n    --eval-replace        if specified, make eval data from --replace(should be\n                            valid Python code). Ignored with --pattern-and-replace\n                            argument.\n    -t, --string          if specified, treats --pattern as string, not as\n                            regular expression. Ignored with --pattern-and-replace\n                            argument.\n    -s \"s/PAT/REP/gixsm\", --pattern-and-replace \"s/PAT/REP/gixsm\", --pattern-and-replace \"s/PAT/REP/gixsm\"\n                            pattern and replacement in one:\n                            s/pattern/replace/g(pattern is always regular\n                            expression, /g is optional and stands for --count=0,\n                            /i == --ignore-case, /s == --pattern-dot-all, /m ==\n                            --pattern-multiline).\n    -c COUNT, --count COUNT\n                            make COUNT replacements for every file (0 makes\n                            unlimited changes, default).\n    -l, --linear          apply pattern for every line separately. Without this\n                            flag whole file is read into memory.\n    -i, --ignore-case     ignore case of characters when matching\n    --pattern-dot-all     with this flag, dot(.) character in pattern match also\n                            new line character (see:\n                            https://docs.python.org/3/library/re.html#re.DOTALL).\n    --pattern-verbose     with this flag pattern can be passed as verbose(see:\n                            https://docs.python.org/3/library/re.html#re.VERBOSE).\n    --pattern-multiline   with this flag pattern can be passed as multiline(see:\n                            https://docs.python.org/3/library/re.html#re.MULTILINE\n                            ).\n    -u, --utf8            Use UTF-8 in --encoding-input, --encoding-file and\n                            --encoding-filesystem\n    --encoding-input ENCODING_INPUT\n                            set encoding for parameters like --pattern etc\n                            (default for your system: utf-8)\n    --encoding-file ENCODING_FILE\n                            set encoding for content of processed files (default\n                            for your system: utf-8)\n    --encoding-filesystem ENCODING_FILESYSTEM\n                            set encoding for paths and filenames (default for your\n                            system: utf-8)\n    -b, --no-backup       don't create backup of modified files.\n    -e EXT, --backup-extension EXT\n                            extension for backup files(ignore if no backup is\n                            created), without leading dot. Defaults to: \"bak\".\n    -W, --expand-wildcards\n                            expand wildcards (see:\n                            https://docs.python.org/3/library/glob.html) in paths\n    --stdin               read data from STDIN(implies --stdout)\n    --stdout              output data to STDOUT instead of change files in-\n                            place(implies --no-backup)\n    -V, --verbose         show files and how many replacements was done and\n                            short summary\n    --debug               show more informations\n    -v, --version         show program's version number and exit\n    \n    Miscellaneous notes:\n    * regular expressions engine used here is PCRE, dialect from Python\n    * is required to pass either --pattern and -replace, or --pattern-and-\n    replace argument\n    * if pattern passed to --pattern-and-replace has /g modifier, it\n    overwrites --count value\n    * if neither /g modifier nor --count argument is passed, assume that\n    --count is equal 1\n    * if only --count is given, this value is used\n    * if --eval-replace is given, --replace must be valid Python code, where\n    can be used m variable. m holds MatchObject instance (see:\n    https://docs.python.org/3/library/re.html#match-objects, for example:\n        --eval-replace --replace 'm.group(1).lower()'\n    * regular expressions with non linear search read whole file to yours\n    computer memory - if file size is bigger then you have memory in your\n    computer, it fails\n    * parsing expression passed to --pattern-and-replace argument is very\n    simple - if you use / as delimiter, then in your expression can't be\n    used this character anymore. If you need to use same character as\n    delimiter and in expression, then better use --pattern and --replace\n    arguments\n    * you can test exit code to verify there was made any changes (exit code\n    = 0) or not (exit code = 1)\n    \n    Security notes:\n    * be careful with --eval-replace argument. When it's given, value passed\n    to --replace is eval-ed, so any unsafe code will be executed!\n    \n    Author:\n    Marcin Sztolcman \u003cmarcin@urzenia.net\u003e // http://urzenia.net\n    \n    HomePage:\n    http://msztolcman.github.io/subst/\n\nMore examples?\n--------------\n\nSimple replace word 'Hello' with 'Hi' in data read from STDIN:\n\n    echo 'Hello World!' | subst -s 's/Hello/Hi/' -\n\nReplace every IP address in form: 192.168.1.X (where X is few digits - single octet)\nwith 192.168.0.X in `/etc/hosts`:\n\n    subst -p '(192\\.168)\\.1\\.(10)' -r '\\1.0.\\2' /etc/hosts\n\nRegular expressions\n-------------------\n\nA.K.A. regex or regexp.\nYou can read more on [Wikipedia](https://en.wikipedia.org/wiki/Regular_expression). Other resources:\n\n- Python documentation on engine `subst` is using: (https://docs.python.org/3/library/re.html)[https://docs.python.org/3/library/re.html]\n- Searchable cheatsheet for Regexps: [https://www.debuggex.com/cheatsheet/regex/pcre](https://www.debuggex.com/cheatsheet/regex/pcre)\n- Regexps tester: [https://www.debuggex.com/?flavor=pcre](https://www.debuggex.com/?flavor=pcre)\n\nInstallation\n------------\n\n`subst` should work on any platform where [Python](http://python.org) is available,\nit means Linux, Windows, MacOS X etc. There is no dependencies, plain Python power :)\n\n1. Installtion using PIP\n\nSimplest way is to use Python's built-in package system:\n\n    pip install subst\n\n2. Using sources\n\nTo install, go to [GitHub releases](https://github.com/msztolcman/subst/releases),\ndownload newest release, unpack and put somewhere in `PATH` (ie. `~/bin`\nor `/usr/local/bin`).\n\nIf You want to install newest unstable version, then just copy file to your PATH,\nfor example:\n\n    curl https://raw.github.com/msztolcman/subst/master/subst.py \u003e /usr/local/bin/subst\n\nor:\n\n    wget https://raw.github.com/msztolcman/subst/master/subst.py -O /usr/local/bin/subst\n\nVoila!\n\nPython compatibility\n--------------------\n\n`subst` is tested against Python 2.7 and Python 3.3+\n\nAuthors\n-------\n\nMarcin Sztolcman \u003cmarcin@urzenia.net\u003e\n\nContact\n-------\n\nIf you like or dislike this software, please do not hesitate to tell me about this me via email (marcin@urzenia.net).\n\nIf you find bug or have an idea to enhance this tool, please use GitHub's [issues](https://github.com/msztolcman/subst/issues).\n\nLicense\n-------\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Marcin Sztolcman\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nChangeLog\n---------\n\n### (dev)\n\n* dropped compatibility with Python 2.6\n* paths are now normalized before processing\n* improvements to handling different encodings\n* exit code give us info about there was any changes\n* added switch --expand-wildcards (-W)\n* added -V switch as an alias for --verbose\n* passing invalid flags to --pattern-and-replace is now an error\n* fixes and improvements in built-in help\n* --pattern-\\* and --ignore-case was ignored for --pattern and --replace parameters\n* --pattern-and-replace was incorrectly parsed with braces as delimiters\n* fixed bug with changing new-line characters from dos to unix (issue #5)\n* fixed bug with bad interpretation of -t param (issue #4)\n* fixed bug with using subst on Windows (issue #2)\n* using singular form in verbose mode when it's required\n* tests are now using py.test framework, also added many new tests\n* many refactorings\n* improvements to pylintrc, Makefile\n* using Pipenv to handling dependencies\n* config for tox\n* marked as compatible with Python 3.5 and 3.6\n\n### v0.4.0\n\n* PEP8 improvements (coding style)\n* Makefile added\n* improved pylintrc\n\n### v0.3.1\n\n* prepared and uploaded to PYPI\n* typos and editorials\n\n### v0.3\n\n* better handling of non-ascii encoding in files, patterns etc\n* higher priority for --pattern-* switches then modifiers in --pattern-and-replace\n* unified switches syntax (was --pattern_and_replace, but other switches used dashes)\n* pep8\n* typos and editorials\n\n### v0.2\n\n* second public version\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsztolcman%2Fsubst","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmsztolcman%2Fsubst","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsztolcman%2Fsubst/lists"}