diff --git a/README.md b/README.md index 87eaad8..33c2341 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![.NET](https://github.com/capjan/regex/actions/workflows/dotnet.yml/badge.svg)](https://github.com/capjan/regex/actions/workflows/dotnet.yml) +[![Coverage](https://raw.githubusercontent.com/capjan/regex/badges/coverage.svg)](https://github.com/capjan/regex/actions/workflows/dotnet.yml) # regex @@ -66,32 +67,191 @@ Exit code is `0` on success and `1` on errors (e.g. missing pattern, invalid reg ## Usage Examples -Find "Hello" in all *.txt files in this folder and all subfolders +Every example is self-contained: the files it starts from, the command, and the exact output. Click to expand. + +
+Search a directory tree for a word in *.txt files + +
+ +Starting point: + ``` -C:>regex --recursive --filter *.txt Hello ./ +docs/ +├── intro.txt "Hello World" / "hello again" / "Goodbye" +└── sub/ + ├── more.txt "Say Hello to everyone" / "nothing here" + └── skip.md "no match" ``` -Search case-sensitive +Command (`--recursive` walks subfolders, `--filter` limits the files, a directory must end with `/`): + ``` -regex --case-sensitive Hello notes.txt +$ regex --recursive --filter '*.txt' Hello docs/ +Offset:0 Hello World +Offset:12 hello again +docs/intro.txt: found 2 matches +Offset:4 Say Hello to everyone +docs/sub/more.txt: found 1 match ``` -Replace with a named group (rewrites the file, files without matches stay untouched) +Matching is case-insensitive by default, so `hello again` is found too. The offset is the character position of the match in the file. `skip.md` is ignored by the filter. + +
+ +
+Case-sensitive search with --case-sensitive + +
+ +`notes.txt`: + ``` -regex "Name:(?[A-Za-z]+)" --replace "Hello ${name}, how are you?" names.txt +Hello there +hello there ``` -Preview a replacement first: `--dry-run` only counts, `--diff` prints a unified diff. Neither writes a file +Default (case-insensitive) versus `--case-sensitive`: + ``` -regex "Name:(?[A-Za-z]+)" --replace 'id=${name}' --diff names.txt +$ regex Hello notes.txt +Offset:0 Hello there +Offset:12 hello there +notes.txt: found 2 matches + +$ regex --case-sensitive Hello notes.txt +Offset:0 Hello there +notes.txt: found 1 match +``` + +
+ +
+Print only the match with --only-matching and --max-count + +
+ +`names.txt`: + ``` +Name:Alice +Name:Bob +Age:42 +``` + +Print just the matched text instead of the whole line: + +``` +$ regex --only-matching 'Name:\w+' names.txt +Name:Alice +Name:Bob +``` + +Stop after the first match: + +``` +$ regex --max-count 1 --only-matching 'Name:\w+' names.txt +Name:Alice +``` + +
+ +
+Replace with a named group (rewrites the file) + +
+ +`names.txt` before: + +``` +Name:Alice +Name:Bob +Age:42 +``` + +Command. Use single quotes in bash/zsh so the shell does not expand `${name}`: -The diff goes to stdout without colors when redirected, so it can be applied later with `patch -p0` or `git apply -p0` (use relative paths, `git apply` rejects absolute ones) ``` -regex "Name:(?[A-Za-z]+)" --replace 'id=${name}' --diff names.txt > names.patch -patch -p0 < names.patch +$ regex 'Name:(?[A-Za-z]+)' --replace 'Hello ${name}, how are you?' names.txt +names.txt: did 2 replacements ``` +`names.txt` after: + +``` +Hello Alice, how are you? +Hello Bob, how are you? +Age:42 +``` + +Files without matches are left untouched. + +
+ +
+Preview a replacement with --dry-run (counts only) + +
+ +`--dry-run` reports what would change and writes nothing. It also works across a whole tree. + +`docs/intro.txt` contains 2 matches for `hello`, `docs/sub/more.txt` contains 1: + +``` +$ regex --recursive --filter '*.txt' --dry-run hello --replace bye docs/ +docs/intro.txt: would do 2 replacements +docs/sub/more.txt: would do 1 replacement +``` + +Both files are unchanged afterwards. + +
+ +
+Preview as unified diff with --diff, then apply it with patch + +
+ +`names.txt`: + +``` +Name:Alice +Name:Bob +Age:42 +``` + +`--diff` prints the changes as a unified diff and writes nothing: + +``` +$ regex 'Name:(?[A-Za-z]+)' --replace 'id=${name}' --diff names.txt +--- names.txt ++++ names.txt +@@ -1,3 +1,3 @@ +-Name:Alice +-Name:Bob ++id=Alice ++id=Bob + Age:42 +``` + +The diff goes to stdout without colors when redirected, so you can save it, review it and apply it later with `patch -p0` or `git apply -p0` (use relative paths, `git apply` rejects absolute ones): + +``` +$ regex 'Name:(?[A-Za-z]+)' --replace 'id=${name}' --diff names.txt > names.patch +$ patch -p0 < names.patch +patching file names.txt +``` + +`names.txt` after `patch`: + +``` +id=Alice +id=Bob +Age:42 +``` + +
+ ## Changelog See [CHANGELOG.md](./CHANGELOG.md).