Why Sponsor Oils? | source | all docs for version 0.22.0 | all versions | oilshell.org
Warning: Work in progress! Leave feedback on Zulip or Github if you'd like this doc to be updated.
Recall that Oil is composed of three interleaved languages: words, commands, and expressions.
This doc describes words, but only the things that are not in:
#word-lang section of OSH Help
Topics#word-lang section of Oil Help
TopicsA word is an expression like $x, "hello $name", or {build,test}/*.py. It
evaluates to a string or an array of strings.
Generally speaking, Oil behaves like a simpler version of POSIX shell / bash. Sophisticated users can read Simple Word Evaluation for a comparison.
Part of an expression:
var x = ${y:-'default'}
Part of a command:
echo ${y:-'default'}
The three contexts where splitting and globbing apply are the ones where a
sequence of words is evaluated (EvalWordSequence):
echo $x foofor i in $x foo; do ...a=($x foo) and var a = :| $x foo | (oil-array)Oil has a new array syntax, but it also supports the bash-compatible syntax:
local myarray=(one two *.py) # bash
var myarray = :| one two *.py | # Oil style
Shell also has contexts where it evaluates words to a single string, rather than a sequence, like:
The behavior of these snippets diverges a lot in existing shells. That is, shells are buggy and poorly-specified.
Oil disallows most of them. Arrays are considered separate from strings and don't randomly "decay".
Related: the RHS of an Oil assignment is an expression, which can be of any type, including an array:
var parts = split(x) # returns an array
var python = glob('*.py') # ditto
var s = join(parts) # returns a string
This is a recap of A Feel for Oil's Syntax.
$ Means "Returns One String"Examples:
All substitutions: var, command, arith
$[a[x+1]] as an expression substitution?$[ /pat+ /]?Inline function calls, a YSH extension: $[join(myarray)]
(C-style strings like $'\n' use $, but that's more of a bash anachronism.
In Oil, c'\n' is preferred.
@ Means "Returns An Array of Strings"Enabled with shopt -s parse_at.
Examples:
@myarray@[arrayfunc(x, y)]These are both Oil extensions.
The array literal syntax also uses a @:
var myarray = :| 1 2 3 |
Uses POSIX behavior for unquoted substitutions like $x.
$IFS.Shell has odd "joining" semantics, which are supported in Oil but generally discouraged:
set -- 'a b' 'c d'
argv.py X"$@"X # => ['Xa', 'b', 'c', 'dX']
In Oil, the RHS of an assignment is an expression, and joining only occurs within double quotes:
# Oil
var joined = $x$y # parse error
var joined = "$x$y" # OK
# Shell
joined=$x$y # OK
joined="$x$y" # OK
Extended globs in OSH are a "legacy syntax" modelled after the behavior of
bash and mksh. This features adds alternation, repetition, and negation to
globs, giving the power of regexes.
You can use them to match strings:
$ [[ foo.cc == *.(cc|h) ]] && echo 'matches' # => matches
Or produce lists of filename arguments:
$ touch foo.cc foo.h
$ echo *.@(cc|h) # => foo.cc foo.h
There are some limitations and differences:
FNM_EXTMATCH extension to fnmatch(). Unlike bash and
mksh, Oil doesn't implement its own extended glob matcher.mksh. When an extended glob appears in a
word, we evaluate the word, match filenames, and skip the rest of the
word evaluation pipeline. This means:
$unquoted/@(*.cc|h)."$@" and extended globs in the same word, e.g.
"$@"_*.@(cc|h). This is usually nonsensical anyway.echo foo > @(cc|h) is a runtime error in OSH, but other
shells will write a file literally named @(cc|h).${undef:-@(cc)}. But it does accept ${x%@(cc)},
since string strip operators like % accept a glob.shopt -s extglob.
bash can't parse some extended globs unless extglob is on. But
it parses others when it's off.PATTERN in ${x//PATTERN/replace}.
This is because we only translate normal (non-extended) globs to regexes (in
order to get the position information necessary for string replacement).shopt --set simple_word_eval (Oil word
evaluation).