An XSH2 expression can be one of the following constructs:

  1. XPath 1.0 expression with the following restriction: whitespace is only allowed within parts the expression enclosed in quotes (literal strings) or brackets (XPath has two types of brackets - plain and square). Thus, while / foo / bar is a valid XPath expression matching element named bar under root element foo, in XSH2 this expression must be written as /foo/bar or (/ foo / bar) or (/foo/bar) etc. The reason for this restriction is simple: XSH2, like most shell languages, uses whitespace as argument delimiter so it must be able to determine expression boundaries (otherwise, / bar / foo could be anything between one and four expressions).

  2. In certain contexts, usually when a filename or a node name is expected as an argument, bareword (otherwise XPath) expressions are evaluated in a non-standard way: as long as the expression contains no whitespace, no brackets of any kind, quotes, double-quotes, $ character, nor @ character, it is treated as a literal token which evaluates to itself. This usually happens if a file name or element name is expected, but some other commands, like print, evaluate its arguments in this way. In order to force an XPath evaluation in such situations, the entire expression should be enclosed with brackets (...). For example, with open command, open file or open "file" both open a file whose name is file (literally) whereas open (file) or open @file compute the file name by evaluating (file) or @file respectively, as XPath expressions.

  3. Perl blocks. These are enclosed in braces like: { perl-code }. Perl expressions can be used to evaluate more complicated things, like complex string expressions, regexp matches, perl commands, etc. In short, arbitrary perl. Of course, things like {`ls`} work too, and that's why we don't need to define shell-like backticks in XSH2 itself.

  4. Result of one XSH2 command can be directly passed as an argument to another. This is done using &{ xsh-code } expressions. Most XSH2 commands always return undef or 1, but some do return a value, usually a node-list. Examples of such commands are open, copy, move, wrap, edit, or xslt.

  5. Large blocks of literal data can be passed to commands via "here document" expressions <<EOF, <<'EOF', <<"EOF", where EOF is an arbitrary ID string. <<EOF and <<"EOF" are equivalent, and are subject to interpolation of ${...} constructs, where as <<'EOF' does not. The result of evaluation of these three is the literal content (with ${...} possibly interpolated) of the script starting at the following line and ending at a line containing just EOF. <<{EOF} and <<(EOF) are implemented too, but I'm not sure they are of any use since putting the expression in ( ) or { } has the same effect.

XPath expressions (and their filename variant) are subject to interpolation of substrings of the form ${...} (called interpolators), where ... can be of several different forms, described below. The interpolation can be suppressed by preceding the $ sign with a backslash.

Substrings of the form ${id} or ${$id} are interpolated with the value of the variable named $id.

Interpolators of the form ${{ and }} evaluate their contents as a Perl expression (in very much the same way as the perl command) and interpolate to the resulting value.

Interpolators of the form ${( and )} evaluate their contents as an XPath expression and interpolates to a string value of the result.

Substrings of the form \${ interpolate to ${ (as a means for escaping ${...} in an expression).

Expressions are evaluated by XSH2 commands themselves, so the exact value an expression evaluates to, is also command-dependent. There are commands that can handle all data types, but some commands expect their arguments to evaluate only to specific kinds of values. As already mentioned above, commands expecting a filename or a node name usually evaluate simple expressions not containing any special characters as literal strings, whereas commands expecting strings evaluate all expressions so that they get a string value (e.g. by converting a node-set to its text content). Similarly, commands expecting a node-set usually convert strings to a small XML fragments, while commands expecting a single document node usually convert node-sets to a document node by taking the owner document of the first element in the node-set.

$a = "bar";              # $a contains: bar
$b = $a;                 # $b contains: bar
$b = "$a";               # $b contains: $a
$b = "${a}";             # $b contains: bar
$b = {$a};               # $b contains: bar
$b = //creature;         # $b contains a node-set
ls $b;                   # prints the node-set as XML in document order
count $b;                # prints number of nodes in the node-set
echo count($b);          # the same
$c = string($b[1]/@name) # $c contains string value of //creature[1]/@name (e.g. Bilbo)
echo //creature          # prints: //creature
echo (//creature)        # evaluates (//creature) as XPath and prints the
# text content of the resulting node-set
echo { join(",",split(//,$a)) }              # prints: b,a,r
echo ${{ join(",",split(//,$a)) }}           # the same
echo "${{ join(",",split(//,$a)) }}"         # the same
echo "${(//creature[1]/@name)}"              # prints e.g.: Bilbo
echo ${(//creature[1]/@name)}                # the same
echo //creature[1]/@name                     # the same
echo string(//creature[1]/@name)             # the same
echo (//creature[1]/@name)                   # the same

Example 65. In-line documents

echo foo <<END baz;
xx ${a} yy
# prints foo xx bar yy baz
echo foo <<"END" baz;
xx ${a} yy
# same as above
echo foo <<'END' baz;
xx ${a} yy
# prints foo xx $a yy baz

Example 66. Expressions returning result of a XSH2 command

copy &{ sort --key @best_score --numeric //player } into .;