13 ms·
Show HN: Xo, a sed-like command line utility that composes regex matches
- ezekg 11y agoSome fun examples of what you can do with `xo`, Hello world: echo 'Hello! My name is C3PO, human cyborg relations.' | xo '/^(\w+)! my name is (\w+)/$1, $2!/i' # => Hello, C3PO! A quick breakdown on the syntax: echo 'Hello! My name is C3PO.' | xo '/^(\w+)?! my name is (\w+)/$1, $2!/i' ^ ^ ^^ ^ ^ ^ ^ |______________________________| ||_______________________| |_____| | | + Delimiter | | + Flag + Piped output + Pattern + Formatter Boot up a Rails server with Stripe keys: # ./secrets/stripe.yml secret_key: fE3J2Z76ry publishable_key qYB7936Qos Then read it and boot Rails with keys set as env vars, (without logging to the console!) cat secrets/stripe.yml | xo '/secret_key:\s([\w]+).*?publishable_key:\s([\w]+)/PUBLISHABLE_KEY=$1 SECRET_KEY=$2 rails s/mis' | sh # => PUBLISHABLE_KEY=fE3J2Z76ry SECRET_KEY=qYB7936Qos rails s View modified files in the last commit: git --no-pager log -n 1 | xo '/^commit\s([^\n]+)/git diff-tree --no-commit-id --name-status -r $1/' | sh # => # M some-modified-file.txt # A some-added-file.txt Nice to put this in a script called `git-last-modified` inside of `/usr/local/bin`, then use `git last-modified`. Decode a hidden message: # ./hidden-message.txt WITHIN THIS MULTILINE the STRING LIES A HIDDEN MESSAGE meaning of life THAT COULD BE is HARD TO READ 42 8) Then read it with, cat hidden-message.text | xo '/([a-z0-9\)]+)/$1/' | xargs # => the meaning of life is 42 8) Read a config file containing SSH info: # ./servers.yml stages: production: server: 192.168.1.1:1234 user: user-1 staging: server: 192.168.1.1 user: user-2 Then read it with, ssh $(cat servers.yml | xo '/.*?(production):\s*server:\s+([^:\n]+):?(\d+)?.*?user:\s+([^\n]+).*/$4@$2 -p $3?:22/mis') # => ssh user-1@192.168.1.1 -p 1234 What if we didn't specify a port, i.e. like staging? Fallback values! (Notice the ternary operator, `?:`) ssh $(cat servers.yml | xo '/.*?(staging):\s*server:\s+([^:\n]+):?(\d+)?.*?user:\s+([^\n]+).*/$4@$2 -p $3?:22/mis') # => ssh user-2@192.168.1.1 -p 22 Now turn that into a `~/.bashrc` function and we're golden, function shh() { ssh $(cat servers.yml | xo "/.*?($1):\s*server:\s+([^:\n]+):?(\d+)?.*?user:\s+([^\n]+).*/\$4@\$2 -p \$3?:22/mis") } And then we can use it like, shh production # => ssh user-1@192.168.1.1 -p 1234
- oleks 11y agoI typically fall back to perl when sed isn't quite versatile/cross-platform enough. What do Go regular expressions offer over Perl regular expressions? (Performance, I imagine.)
- ezekg 11y agoDefinitely performance. Go doesn't support negative/positive lookaheads (for performance/efficiency reasons, apparently), so that's really the only downside I've found with Go's regular expressions.
- voaie 11y agoObviously it is not line-oriented. So the selling points are? 1. custom delimiters 2. special syntax for fallback values 3. extended regular expression with Unicode support More?
- ezekg 11y agoWell, it can be line-oriented. It just depends on the regexp pattern and flags specified, i.e. `/^somePattern/someFormatter/` vs `/^somePattern/someFormatter/ms` (`m` flag to enable multi-line mode, `s` to let `.` match `\n`). It has support for multi-line matches, as well as matching per-line. Maybe I'm just misunderstanding you. Go's regexp syntax: https://golang.org/pkg/regexp/syntax/ https://golang.org/pkg/regexp/syntax/