Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

pepa65/esed

 
 

Repository files navigation

version build dependencies docs license downloads

esed 1.1.6

Easy sed

The Pitch

Why use it over any existing tools?

  • Painless regular expressions - esed uses Rust regex syntax that is very feature-rich. Forget about dealing with quirks of sed or awk and get productive immediately.
  • Easy to read, easy to write - Search & replace expressions are split up, which makes them easy to read and write. No more messing with unclosed and escaped slashes.
  • Optional String-literal mode - Non-regex search & replace: no more backslashes, no more remembering which characters are special and need to be escaped.
  • Easy to modify multiple files - No for-loops needed, just list all files or use shell-wildcards.
  • Smart, common-sense defaults - Defaults follow common sense and are tailored for typical daily use.
  • Still need -i/--in-place to modify files - Defaults to output to stdout for safety.

Comparison to sed

While sed does a whole lot more, esed focuses on doing just one thing and doing it well. Here are some cherry-picked examples where esed shines:

  • Simpler syntax for replacing all occurrences:
    • esed: esed SEARCH REPLACEMENT
    • sed: sed s/SEARCH/REPLACEMENT/g
  • Replace newlines with comma-space:
    • esed: esed '\n' ', '
    • sed: sed ':a;N;$!ba;s/\n/, /g'
  • Extracting stuff surrounded ny slashes out of string:
    • esed: echo "Example with /path/, etc." |esed '.*(/.*/)' '$1'
    • sed: echo "Example with /path/, etc." |sed -E 's/.*(\\/.*\\/)/\1/g'
    • Or sed with a different delimiter (still messy): echo "Example with /path/ etc." |sed -E 's@.*(/.*/)@\1@g'
  • In place modification of file:
    • esed: esed -i SEARCH REPLACEMENT FILE
    • sed: sed -i -e 's/SEARCH/REPLACEMENT/g' FILE (some platforms do not need the -e)
  • Replacement in multiple files:
    • esed: esed -i SEARCH REPLACEMENT FILE* XFILE STHFILE
    • sed: for file in FILE* XFILE STHFILE; do sed -i -e 's/SEARCH/REPLACEMENT/g' "$file"; done

Notes on regex syntax

  • Common regex features like start & end anchors ^ #, dot . wildcard (unicode) character matching, character class matching between square brackets [ ] and character exclusion between [^ and ].
  • Quantifiers (after the pattern): *: 0 or more, +: 1 or more, ?: 0 or 1, {n,m}: between n and m times
  • Alternation: | matches either the pattern on the left or the right.
  • Escape special characters (. * & $) by prefixing with \\. In REPLACEMENT use $$ to escape $.
  • Special matchings: \s: whitespace, \S: non-whitespace, \d: digit, \pL: letter (any unicode class) \n: newline, \r: carriagereturn, \t: tab
  • Non-unicode matching between (?-u: and )
  • Grouping between parentheses ( ) enables capturing patterns in the replacement and combining/grouping.
  • Named grouping between (?P<NAME> and ).
  • For full documentation, see: https://docs.rs/regex/latest/regex/#syntax

Benchmarks

Simple replacement on ~1.5 gigabytes of JSON files

hyperfine --warmup 3 --export-markdown out.md \
  'sed -E "s/\"/'"'"'/g" *.json >/dev/null' \
  'sed "s/\"/'"'"'/g" *.json >/dev/null' \
  'esed -i "\"" "'"'"'" *.json >/dev/null'
Command Mean [s] Min…Max [s]
sed -E "s/\"/'/g" *.json > /dev/null 2.338 ± 0.008 2.332…2.358
sed "s/\"/'/g" *.json > /dev/null 2.365 ± 0.009 2.351…2.378
esed "\"" "'" *.json > /dev/null 0.997 ± 0.006 0.987…1.007

Result: ~2.35 times faster

Regex replacement on a ~55M json file

hyperfine --warmup 3 --export-markdown out.md \
  'sed -E "s:(\w+):\1\1:g" dump.json >/dev/null' \
  'sed "s:\(\w\+\):\1\1:g" dump.json >/dev/null' \
  'esed "(\w+)" "$1$1" dump.json >/dev/null'
Command Mean [s] Min…Max [s]
sed -E "s:(\w+):\1\1:g" dump.json >/dev/null 11.315 ± 0.215 11.1.4…11.725
sed "s:\(\w\+\):\1\1:g" dump.json >/dev/null 11.239 ± 0.208 11.057…11.762
esed "(\w+)" "$1$1" dump.json >/dev/null 0.942 ± 0.004 0.936…0.951

Result: ~11.93 times faster

Install

Download and install static single-binary

wget https://github.com/pepa65/esed/releases/download/1.1.6/esed
sudo mv esed /usr/local/bin
sudo chown root:root /usr/local/bin/esed
sudo chmod +x /usr/local/bin/esed

Install with cargo

If not installed yet, install a Rust toolchain, see https://www.rust-lang.org/tools/install

The binary esed will be installed into ~/.cargo/bin/ (might need to be added to PATH!)

Direct from crates.io

cargo install esed

Direct from repo

cargo install --git https://github.com/pepa65/esed

Static build for Linux (avoiding GLIBC incompatibilities)

git clone https://github.com/pepa65/esed
cd esed
rustup target add x86_64-unknown-linux-musl
cargo inst  # Alias defined in .cargo/config.toml

Install with cargo-binstall

Even without a full Rust toolchain, rust binaries can be installed with the static binary cargo-binstall:

# Install cargo-binstall for Linux x86_64
# (Other versions are available at https://crates.io/crates/cargo-binstall)
wget github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-x86_64-unknown-linux-musl.tgz
tar xf cargo-binstall-x86_64-unknown-linux-musl.tgz
sudo chown root:root cargo-binstall
sudo mv cargo-binstall /usr/local/bin/

Only a linux-x86_64 (musl) binary available: cargo-binstall esed

This will also be installed into ~/.cargo/bin/ and might need to be added to PATH!

Quick Guide

  1. String-literal mode: By default, expressions are treated as regex. Use -s/--strings to disable regex.
    # Remove string with special characters
    echo 'lots((([]))) of special chars' |esed -s '((([])))' ''
    # Result: "lots of special chars"
  2. Basic regex use: Trim trailing whitespace.
    # Trim whitespace before the end of input
    echo 'lorem ipsum 23   ' |esed '\s+$' ''
    # Result: "lorem ipsum 23"
  3. Capture groups: Can be indexed (numbered) or named
    • Indexed capture groups:
      echo 'cargo +nightly watch' |esed '(\w+)\s+\+(\w+)\s+(\w+)' 'cmd: $1, channel: $2, subcmd: $3'
      # Result: "cmd: cargo, channel: nightly, subcmd: watch"
    • Named capture groups:
      echo "123.45" |esed '(?P<dollars>\d+)\.(?P<cents>\d+)' '$dollars dollars and $cents cents'
      # Result: 123 dollars and 45 cents
      If stumbling upon ambiguities, use ${var} instead of $var, like:
      echo '123.45' |esed '(?P<dollars>\d+)\.(?P<cents>\d+)' '${dollars}_dollars and ${cents}_cents'
      # Result: "123_dollars and 45_cents"
  4. Search & replace in a file
    esed -i 'window.fetch' 'fetch' http.js
    To preview changes (the -i/--in-place flag needs to be given to modify files):
    esed 'window.fetch' 'fetch' http.js
  5. Search & replace across project
    esed 'from "react"' 'from "preact"' ../*/*.json

Usage

esed v1.1.6 - Easy sed

Usage: esed [OPTIONS] <SEARCH> <REPLACEMENT> [FILE]...
Arguments:
  <SEARCH>       SEARCH: regexp or (if using '-s'/'--strings') string
  <REPLACEMENT>  REPLACEMENT (regex captured values like $1 can be used)
  [FILE]...      Optional path(s) to file(s)

Options:
  -i, --in-place           Modify file(s) in-place instead of output to stdout
  -s, --strings            Treat SEARCH and REPLACEMENT as literal strings [default: regex]
  -c, --case-insensitive   Use regex case-insensitive [default: case-sensitive]
  -w, --word               Match the SEARCH regex as a full word [default: match anywhere]
  -d, --dot-match-newline  Dots also match newlines [default: newlines not matched by dots]
  -n, --no-multiline       No multiline: '^' and '$' anchor only to the very beginning and end [default: multiline]
  -l, --limit <MAX>        Limit the number of replacements per file (0: unlimited) [default: 0]
  -h, --help               Print help
  -V, --version            Print version

About

Easy sed

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust 100.0%