An XSH2 expression can be one of the following constructs:
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).
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.
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.
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.
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
$a="bar"
echo foo <<END baz; xx ${a} yy END # prints foo xx bar yy baz
echo foo <<"END" baz; xx ${a} yy END # same as above
echo foo <<'END' baz; xx ${a} yy END # prints foo xx $a yy baz
Example 66. Expressions returning result of a XSH2 command
copy &{ sort --key @best_score --numeric //player } into .;