| .circleci | ||
| .clj-kondo | ||
| .github/ISSUE_TEMPLATE | ||
| doc | ||
| resources | ||
| script | ||
| src | ||
| test/babashka | ||
| .gitignore | ||
| LICENSE | ||
| project.clj | ||
| README.md | ||
| reflection.json | ||
babashka
A pure, fast and (severely!) limited version of Clojure in Clojure for shell scripting.
Properties:
- pure (no side effects)
- fast startup time
- interprets only one form
- reads from stdin and writes to stdout
Rationale
Most of your script is in bash, but you want a tiny sprinkle of Clojure.
If most of your shell script evolves into Clojure, you might want to turn to:
Status
Experimental. Breaking changes are expected to happen at this phase.
Installation
Linux and macOS binaries are provided via brew.
Install:
brew install borkdude/brew/babashka
Upgrade:
brew upgrade babashka
You may also download a binary from Github.
Usage
... | bb [-i] [-o] '<Clojure form>'
There is one special variable, *in*, which is the input read from stdin. The
input is read as EDN by default, unless the -i flag is provided, then the
input is read as a string split by newlines into a vector.. The output is
printed as EDN by default, unless the -o flag is provided, then the output is
printed using println. To combine -i and -o you can use -io.
The current version can be printed with bb --version.
Currently only the macros if, when, and, or, -> and ->> are
supported.
Examples:
$ ls | bb -i '*in*'
["LICENSE" "README.md" "bb" "doc" "pom.xml" "project.clj" "reflection.json" "resources" "script" "src" "target" "test"]
$ ls | bb -i '(count *in*)'
12
$ bb '(vec (dedupe *in*))' <<< '[1 1 1 1 2]'
[1 2]
$ bb '(filterv :foo *in*)' <<< '[{:foo 1} {:bar 2}]'
[{:foo 1}]
Anonymous functions literals are allowed with currently up to three positional arguments.
$ bb '(#(+ %1 %2 %3) 1 2 *in*)' <<< 3
6
$ ls | bb -i '(filterv #(re-find #"reflection" %) *in*)'
["reflection.json"]
Shuffle the lines of a file:
$ cat /tmp/test.txt
1 Hello
2 Clojure
3 Babashka
4 Goodbye
$ < /tmp/test.txt bb -io '(shuffle *in*)'
3 Babashka
2 Clojure
4 Goodbye
1 Hello
Find the line numbers where the word Clojure occurs using a case insensitive regex:
$ cat /tmp/test.txt
foo
Clojure is nice
bar
when you're nice to clojure
$ < /tmp/test.txt bb -i '(map-indexed #(vector %1 %2) *in*))' | \
bb '(keep #f(when (re-find #"(?i)clojure" (second %)) (first %)) *in*)'
(1 3)
Test
Test on the JVM:
script/test
Although this tool doesn't offer any benefit when running on the JVM, it is convenient for development.
Test the native version:
BABASHKA_TEST_ENV=native script/test
Build
You will need leiningen and GraalVM.
script/compile
Gallery
Here's a gallery of more useful examples. Do you have a useful example? PR welcome!
Fetch latest Github release tag
For converting JSON to EDN, see jet.
$ curl -s https://api.github.com/repos/borkdude/babashka/tags \
| jet --from json --keywordize --to edn \
| bb '(-> *in* first :name (subs 1))'
"0.0.4"
Download latest linux version of babashka
$ curl -s https://api.github.com/repos/borkdude/babashka/releases \
| jet --from json --keywordize \
| bb '(-> *in* first :assets)' \
| bb '(keep #(re-find #"^.*linux.*" (:browser_download_url %)) *in*)' \
| bb -o '(first *in*)' \
| xargs -n1 curl -sL > /tmp/bb
License
Copyright © 2019 Michiel Borkent
Distributed under the EPL License, same as Clojure. See LICENSE.