OILS / doc / upgrade-breakage.md View on Github | oilshell.org

198 lines, 124 significant
1---
2default_highlighter: oils-sh
3---
4
5What Breaks When You Upgrade to YSH
6===================================
7
8Only a few things break when you put this at the top of a shell script:
9
10 shopt --set ysh:upgrade
11
12This doc enumerates and explains them.
13
14<div id="toc">
15</div>
16
17## Reasons for Upgrading
18
19First, let's emphasize the **good** things that happen when you upgrade:
20
21- You can write `if (x > 0)` instead of `if [ "$x" -gt 0 ]`.
22- You can pass blocks to commands, like `cd /tmp { echo $PWD }`
23- [Simple Word Evaluation](simple-word-eval.html): You can write `$var` instead
24 of `"$var"`, and splice arrays with `@myarray`.
25- [Reliable Error Handling](error-handling.html) becomes the default.
26- ... and more
27
28You can also use `bin/osh` indefinitely, in which case you don't need to read
29this doc. [OSH]($xref:osh-language) is a highly compatible Unix shell.
30
31## Syntax Changes
32
33Now onto the breakages. Most of them are **unlikely**, but worth noting.
34
35### `if ( )` and `while ( )` take expressions, not subshell commands
36
37Code like `if ( ls /tmp )` is valid shell, but it's almost always a misuse of
38the language. Parentheses mean **subshell**, not grouping as in C or Python.
39
40In YSH:
41
42- Use `if (x > 0)` for true/false expressions
43- Use the `forkwait` builtin for subshells, which are uncommon. (It's like
44 invoking the `fork` builtin, then the `wait` builtin.)
45
46No:
47
48 ( cd /tmp; rm *.sh )
49
50Yes:
51
52 forkwait {
53 cd /tmp
54 rm *.sh
55 }
56
57Better:
58
59 cd /tmp { # no process created
60 rm *.sh
61 }
62 echo $PWD # restored
63
64
65(Option `parse_paren` is part of group `ysh:upgrade`.)
66
67### `@()` is spliced command sub, not extended glob
68
69YSH doesn't have implicit word splitting, so we want `@(seq 3)` to be
70consistent with `$(hostname)`. They're related in the same way that `@myarray`
71and `$mystr` are.
72
73This means that `@()` is no longer extended glob, and `,()` is an alias.
74
75No:
76
77 echo @(*.cc|*.h)
78
79Use this YSH alias instead:
80
81 echo ,(*.cc|*.h)
82
83(Option `parse_at` is part of group `ysh:upgrade`.)
84
85### `r'c:\Users\'` is a raw string, not joined strings
86
87The meaning of `\` within string literals can be confusing, so YSH
88distinguishes them like this:
89
90- `$'foo\n'`
91 - The `$` prefix means that C-style backslash escapes are respected.
92- `r'c:\Users\'`
93 - The `r` prefix means the backslashes are literal.
94 - In shell this is written `'c:\Users\'`. YSH accepts this in command mode
95 for compatibility, but not expression mode.
96
97The prefix **changes** the meaning of commands like:
98
99 echo r'foo'
100 # => foo in YSH
101 # => rfoo in shell, because of implicit joining
102
103Instead, write `'rfoo'` if that's what you mean.
104
105(Option `parse_raw_string` is part of group `ysh:upgrade`.)
106
107### globs can't start with `[`
108
109In a command, the `[` character starts a lazy arg list:
110
111 assert [42 === x]
112
113In shell, `[` is part of the glob syntax:
114
115 echo [ch] # extremely rare pattern matching c or h
116
117This is more common, and still works:
118
119 echo *.[ch]
120
121You can still express the former by explicitly invoking `glob('[ch]')`.
122
123
124(Option `parse_bracket` is part of group `ysh:upgrade`.)
125
126## Unsupported
127
128### Extended Globs in Word Evaluation
129
130Like regular globs, the extended glob syntax is used in two ways:
131
1321. Pattern matching
133 - `case`
134 - Bash boolean expressions like `[[ x == !(*.cc|*.h) ]]`
1352. Word Evaluation
136 - commands like `cp !(*.cc|*.h) /tmp`
137 - arrays like `local -a myarray=( !(*.cc|*.h) )`
138 - Shell-style `for` loops
139
140Extended globs are **not** supported in [Simple Word
141Evaluation](simple-word-eval.html), so you can't use them in the second way
142after upgrading.
143
144You may want to use the `find` command or [Egg expressions](eggex.html)
145instead.
146
147(Option `simple_word_eval` is part of group `ysh:upgrade`.)
148
149## More Quotes May Be Needed
150
151### With `ysh:upgrade` Options
152
153Option `parse_at`. In YSH, `@` is used to splice arrays. To pass a string
154`@foo` to a command, quote it like `'@foo'`.
155
156Option `parse_brace`. Braces after commands start block arguments. To change
157to a directory named `{`, quote it like `cd '{'`.
158
159Option `parse_equals`. A statement like `x = 42` is a "bare assignment" or
160attribute. To pass `=` to a command `x`, quote it like `x '='`.
161
162### Unconditionally
163
164- To avoid confusion with YSH's `=` operator, a word like `=x` can't be the first word in a command.
165 To invoke such commands, quote them like `'=x'`.
166- YSH has new keywords like `proc`, `const`, `var`, and `setvar`. To use them
167 as command names, quote them like `'proc'`.
168
169There is very little reason to use commands like `'=x'` and `'proc'`, so you
170will likely never run into this!
171
172## Summary
173
174This concludes the list of features that's broken when you upgrade from OSH to
175YSH. We tried to keep this list as small as possible.
176
177There are other features that are **discouraged**, like `$(( x + 1 ))`, `(( i++
178))`, `[[ $s =~ $pat ]]`, and `${s%%prefix}`. These have better alternatives in
179the YSH expression language, but they can still be used. See [YSH vs. Shell
180Idioms](idioms.html).
181
182Also related: [Known Differences Between OSH and Other
183Shells](known-differences.html).
184
185## Appendix
186
187### Shell Functions vs. Procs
188
189Procs have truly local variables like Python and JavaScript. There's no
190[dynamic scope]($xref:dynamic-scope) rule, as with shell functions.
191
192This is something to be aware of, but isn't technically a breakage because
193shell functions still work the same way in YSH.
194
195### Acknowledgments
196
197Thank you to `ca2013` for reviewing this doc.
198