OILS / doc / ref / chap-word-lang.md View on Github | oils.pub

452 lines, 308 significant
1---
2title: Word Language (Oils Reference)
3all_docs_url: ..
4body_css_class: width40
5default_highlighter: oils-sh
6preserve_anchor_case: yes
7---
8
9<div class="doc-ref-header">
10
11[Oils Reference](index.html) &mdash;
12Chapter **Word Language**
13
14</div>
15
16This chapter describes the word language for OSH and YSH. Words evaluate to
17strings, or arrays of strings.
18
19<span class="in-progress">(in progress)</span>
20
21<div id="dense-toc">
22</div>
23
24<h2 id="expression">Expressions to Words</h2>
25
26### expr-sub
27
28Try to turn an expression into a string. Examples:
29
30 $ echo $[3 * 2]
31 6
32
33 $ var s = 'foo'
34 $ echo $[s[1:]]
35 oo
36
37Some types can't be stringified, like Dict and List:
38
39 $ var d = {k: 42}
40
41 $ echo $[d]
42 fatal: expected Null, Bool, Int, Float, Eggex
43
44You can explicitly use `toJson8` or `toJson()`:
45
46 $ echo $[toJson8(d)]
47 {"k":42}
48
49(This is similar to `json write (d)`)
50
51### expr-splice
52
53Splicing puts the elements of a `List` into a string array context:
54
55 $ var foods = ['ale', 'bean', 'corn']
56 $ echo pizza @[foods[1:]] worm
57 pizza bean corn worm
58
59This syntax is enabled by `shopt --set` [parse_at][], which is part of YSH.
60
61[parse_at]: chap-option.html#ysh:upgrade
62
63### var-splice
64
65 $ var foods = ['ale', 'bean', 'corn']
66 echo @foods
67
68This syntax is enabled by `shopt --set` [parse_at][], which is part of YSH.
69
70
71<h2 id="formatting">Formatting Typed Data as Strings</h2>
72
73### ysh-printf
74
75Not done.
76
77 echo ${x %.3f}
78
79### ysh-format
80
81Not done.
82
83 echo ${x|html}
84
85## Quotes
86
87### osh-string
88
89- Single quotes
90- Double Quotes
91- C-style strings: `$'\n'`
92
93TODO: elaborate
94
95### ysh-string
96
97YSH strings in the word language are the same as in the expression language.
98
99See [ysh-string in chap-expr-lang](chap-expr-lang.html#ysh-string).
100
101### triple-quoted
102
103Triple-quoted in the word language are the same as in the expression language.
104
105See [triple-quoted in chap-expr-lang](chap-expr-lang.html#triple-quoted).
106
107### tagged-str
108
109Not done.
110
111## Substitutions
112
113### command-sub
114
115Executes a command and captures its stdout.
116
117OSH has shell-compatible command sub like `$(echo hi)`. If a trailing newline
118is returned, it's removed:
119
120 $ hostname
121 example.com
122
123 $ echo "/tmp/$(hostname)"
124 /tmp/example.com
125
126YSH has spliced command subs, enabled by `shopt --set parse_at`. The result is
127a **List** of strings, rather than a single string.
128
129 $ write -- @(echo foo; echo 'with spaces')
130 foo
131 with-spaces
132
133The command's stdout parsed as the "J8 Lines" format, where each line is
134either:
135
1361. An unquoted string, which must be valid UTF-8. Whitespace is allowed, but
137 not other ASCII control chars.
1382. A quoted J8 string (JSON style `""` or J8-style `b'' u'' ''`)
1393. An **ignored** empty line
140
141See [J8 Notation](../j8-notation.html) for more details.
142
143### var-sub
144
145Evaluates to the value of a variable:
146
147 $ x=X
148 $ echo $x ${x}
149 X X
150
151### arith-sub
152
153Shell has C-style arithmetic:
154
155 $ echo $(( 1 + 2*3 ))
156 7
157
158### tilde-sub
159
160Used as a shortcut for a user's home directory:
161
162 ~/src # my home dir
163 ~bob/src # user bob's home dir
164
165### proc-sub
166
167Open stdout as a named file in `/dev/fd`, which can be passed to a command:
168
169 diff <(sort L.txt) <(sort R.txt)
170
171Open stdin as a named file in `/dev/fd`:
172
173 seq 3 | tee >(sleep 1; tac)
174
175
176## Var Ops
177
178There are three types of braced variable expansions:
179
180 ${!name*} or ${!name@}
181 ${!name[@]} or ${!name[*]}
182 ${ops var ops}
183
184`name` needs to be a valid identifier. If the expansion matches the first
185form, the variable names starting with `name` are generated. Otherwise, if the
186expansion matches the second form, the keys of the indexed or associative array
187named `name` are generated. When the expansion does not much either the first
188or second forms, it is interpreted as the third form of the variable name
189surrounded by operators.
190
191
192### op-bracket
193
194The suffix operator of the form `[key]` is used to reference inner strings of
195the operand value. For an indexed array `${array[index]}` can be used to
196specify an array element at offset `index`, where `index` undergoes arithmetic
197evaluation. For an associated array, `${assoc[key]}` can be used to specify a
198value associated with `key`. A scalar value is treated as if an indexed array
199with a single element, with itself contained at index 0.
200
201`[*]` and `[@]` are the special cases, which override the normal meaning. Both
202generate a word list of all elements in the operand. When the variable
203substituion is unquoted by double quotations, there is no difference between
204`[*]` and `[@]`:
205
206 $ IFS=x
207 $ a=(1 2 3)
208 $ printf '<%s>\n' ${a[*]}
209 <1>
210 <2>
211 <3>
212 $ printf '<%s>\n' ${a[@]}
213 <1>
214 <2>
215 <3>
216
217When the variable substituion is inside double quotations, the `[*]` form joins
218the elements by the first character of `IFS`:
219
220 $ printf '<%s>\n' "${a[*]}"
221 <1x2x3>
222
223The `[@]` form quoted inside double quotation generates a word list by spliting
224the word at the boundary of every element pair in the operand:
225
226 $ printf '<%s>\n' "A${a[@]}Z"
227 <A1>
228 <2>
229 <3Z>
230
231If the operand has no element and the word is just double quotation of only the
232variable substitution, `[@]` results in an empty word list:
233
234 $ empty=()
235 $ set -- "${empty[@]}"
236 $ echo $#
237 0
238
239These rules for `[*]` and `[@]` also apply to `$*` and `$@`, `${!name*}` and
240`${!name@}`, `${!name[*]}` and `${!name[@]}`, etc.
241
242Note: OSH currently joins the values by `IFS` even for unquoted `$*` and
243performs word splitting afterward. This is different from the POSIX standard.
244
245### op-indirect
246
247The indirection operator `!` is a prefix operator, and it interprets the
248received string as a variable name `name`, an array element `name[key]`, or an
249arrat list `name[@]` / `name[*]` and reads its values.
250
251 $ a=1234
252 $ v=a
253 $ echo $v
254 a
255 $ echo ${!v}
256 1234
257
258### op-test
259
260Shell has boolean operations within `${}`. I use `:-` most frequently:
261
262 x=${1:-default}
263 osh=${OSH:-default}
264
265This idiom is also useful:
266
267 : ${LIB_OSH=stdlib/osh}
268
269The colonless form checks whether the value exists. It evaluates to `false` if
270the variable is unset. In the case of a word list generated by e.g. `$*` and
271`$@`, it tests whether there is at least one element.
272
273The form with a colon checks whether the resulting string is non-empty. In the
274case of a word list generated by e.g. `$*` and `$@`, the test is performed
275after joining the elements by a space ` `. It should be noted that elements
276are joined by the first character of `IFS` only with double-quoted `"${*:-}"`,
277while `${*:-}`, `${@:-}`, and `"${@:-}"` are joined by a space ` `. This is
278because the joining of `"$*"` by `IFS` is performed earlier than the joining by
279` ` for the test.
280
281Note: OSH currently joins the values by `IFS` even for unquoted `$*`. This is
282different from Bash.
283
284### op-strip
285
286Remove prefixes or suffixes from strings:
287
288 echo ${y#prefix}
289 echo ${y##'prefix'}
290
291 echo ${y%suffix}
292 echo ${y%%'suffix'}
293
294The prefix and suffix can be glob patterns, but this usage is discouraged
295because it may be slow.
296
297### op-patsub
298
299Replace a substring or pattern.
300
301The character after the first `/` can be `/` to replace all occurrences:
302
303 $ x=food
304
305 $ echo ${x//o/--} # replace 1 o with 2 --
306 f----d
307
308It can be `#` or `%` for an anchored replacement:
309
310 $ echo ${x/#f/--} # left anchored f
311 --ood
312
313 $ echo ${x/%d/--} # right anchored d
314 foo--
315
316The pattern can also be a glob:
317
318 $ echo ${x//[a-z]/o} # replace 1 char with o
319 oooo
320
321 $ echo ${x//[a-z]+/o} # replace multiple chars
322 o
323
324### op-slice
325
326 echo ${a[@]:1:2}
327 echo ${@:1:2}
328
329### op-format
330
331${x@P} evaluates x as a prompt string, i.e. the string that would be printed if
332PS1=$x.
333
334---
335
336`${x@Q}` quotes the value of `x`, if necessary, so that it can be evaluated as
337a shell word.
338
339 $ x='<'
340 $ echo "value = $x, quoted = ${x@Q}."
341 value = <, quoted = '<'.
342
343 $ x=a
344 $ echo "value = $x, quoted = ${x@Q}."
345 value = a, quoted = a.
346
347In the second case, the string `a` doesn't need to be quoted.
348
349---
350
351Format operations like `@Q` generally treat **empty** variables differently
352than **unset** variables.
353
354That is, `${empty@Q}` is the string `''`, while `${unset@Q}` is an empty
355string:
356
357 $ x=''
358 $ echo "value = $x, quoted = ${x@Q}."
359 value = , quoted = ''.
360
361 $ unset -v x
362 $ echo "value = $x, quoted = ${x@Q}."
363 value = , quoted = .
364
365---
366
367`${x@a}` returns characters that represent the attributes of the `${x}`, or
368more precisely, the *h-value* of `${x}`.
369
370Definitions:
371
372- *h-value* is the variable (or the object that the variable directly points)
373 from which the result of `${x}` would originally come.
374- *r-value* is the value of the expansion of `${x}`
375
376For example, with `arr=(1 2 3)`:
377
378<style>
379table {
380 width: 100%;
381 margin-left: 2em; /* matches p text in manual.css */
382}
383thead {
384 text-align: left;
385}
386</style>
387
388<table>
389
390- thead
391 - Reference
392 - Expression
393 - H-value
394 - R-value
395 - Flags returned
396- tr
397 - <!-- empty -->
398 - `${arr[0]@a}` or <br/> `${arr@a}`
399 - array<br/> `(1 2 3)`
400 - string<br/> `1`
401 - `a`
402- tr
403 - <!-- empty -->
404 - `${arr[@]@a}`
405 - array<br/> `(1 2 3)`
406 - array<br/> `(1 2 3)`
407 - `a a a`
408- tr
409 - `ref=arr` or `ref=arr[0]`
410 - `${!ref@a}`
411 - array<br/> `(1 2 3)`
412 - string<br/> `1`
413 - `a`
414 - <!-- empty -->
415- tr
416 - `ref=arr[@]`
417 - `${!ref@a}`
418 - array<br/> `(1 2 3)`
419 - array<br/> `(1 2 3)`
420 - `a a a`
421
422</table>
423
424When `${x}` would result in a word list, `${x@a}` returns a word list
425containing the attributes of the *h-value* of each word.
426
427---
428
429These characters may be returned:
430
431<table>
432
433- thead
434 - Character
435 - Where `${x}` would be obtained
436- tr
437 - `a`
438 - indexed array
439- tr
440 - `A`
441 - associative array
442- tr
443 - `r`
444 - readonly container
445- tr
446 - `x`
447 - exported variable
448- tr
449 - `n`
450 - name reference (OSH extension)
451
452</table>