1 | ---
|
2 | default_highlighter: oils-sh
|
3 | ---
|
4 |
|
5 | What Breaks When You Upgrade to YSH
|
6 | ===================================
|
7 |
|
8 | Only a few things break when you put this at the top of a shell script:
|
9 |
|
10 | shopt --set ysh:upgrade
|
11 |
|
12 | This doc enumerates and explains them.
|
13 |
|
14 | <div id="toc">
|
15 | </div>
|
16 |
|
17 | ## Reasons for Upgrading
|
18 |
|
19 | First, 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 |
|
28 | You can also use `bin/osh` indefinitely, in which case you don't need to read
|
29 | this doc. [OSH]($xref:osh-language) is a highly compatible Unix shell.
|
30 |
|
31 | ## Syntax Changes
|
32 |
|
33 | Now onto the breakages. Most of them are **unlikely**, but worth noting.
|
34 |
|
35 | ### `if ( )` and `while ( )` take expressions, not subshell commands
|
36 |
|
37 | Code like `if ( ls /tmp )` is valid shell, but it's almost always a misuse of
|
38 | the language. Parentheses mean **subshell**, not grouping as in C or Python.
|
39 |
|
40 | In 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 |
|
46 | No:
|
47 |
|
48 | ( cd /tmp; rm *.sh )
|
49 |
|
50 | Yes:
|
51 |
|
52 | forkwait {
|
53 | cd /tmp
|
54 | rm *.sh
|
55 | }
|
56 |
|
57 | Better:
|
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 |
|
69 | YSH doesn't have implicit word splitting, so we want `@(seq 3)` to be
|
70 | consistent with `$(hostname)`. They're related in the same way that `@myarray`
|
71 | and `$mystr` are.
|
72 |
|
73 | This means that `@()` is no longer extended glob, and `,()` is an alias.
|
74 |
|
75 | No:
|
76 |
|
77 | echo @(*.cc|*.h)
|
78 |
|
79 | Use 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 |
|
87 | The meaning of `\` within string literals can be confusing, so YSH
|
88 | distinguishes 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 |
|
97 | The 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 |
|
103 | Instead, 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 |
|
109 | In a command, the `[` character starts a lazy arg list:
|
110 |
|
111 | assert [42 === x]
|
112 |
|
113 | In shell, `[` is part of the glob syntax:
|
114 |
|
115 | echo [ch] # extremely rare pattern matching c or h
|
116 |
|
117 | This is more common, and still works:
|
118 |
|
119 | echo *.[ch]
|
120 |
|
121 | You 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 |
|
130 | Like regular globs, the extended glob syntax is used in two ways:
|
131 |
|
132 | 1. Pattern matching
|
133 | - `case`
|
134 | - Bash boolean expressions like `[[ x == !(*.cc|*.h) ]]`
|
135 | 2. Word Evaluation
|
136 | - commands like `cp !(*.cc|*.h) /tmp`
|
137 | - arrays like `local -a myarray=( !(*.cc|*.h) )`
|
138 | - Shell-style `for` loops
|
139 |
|
140 | Extended globs are **not** supported in [Simple Word
|
141 | Evaluation](simple-word-eval.html), so you can't use them in the second way
|
142 | after upgrading.
|
143 |
|
144 | You may want to use the `find` command or [Egg expressions](eggex.html)
|
145 | instead.
|
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 |
|
153 | Option `parse_at`. In YSH, `@` is used to splice arrays. To pass a string
|
154 | `@foo` to a command, quote it like `'@foo'`.
|
155 |
|
156 | Option `parse_brace`. Braces after commands start block arguments. To change
|
157 | to a directory named `{`, quote it like `cd '{'`.
|
158 |
|
159 | Option `parse_equals`. A statement like `x = 42` is a "bare assignment" or
|
160 | attribute. 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 |
|
169 | There is very little reason to use commands like `'=x'` and `'proc'`, so you
|
170 | will likely never run into this!
|
171 |
|
172 | ## Summary
|
173 |
|
174 | This concludes the list of features that's broken when you upgrade from OSH to
|
175 | YSH. We tried to keep this list as small as possible.
|
176 |
|
177 | There are other features that are **discouraged**, like `$(( x + 1 ))`, `(( i++
|
178 | ))`, `[[ $s =~ $pat ]]`, and `${s%%prefix}`. These have better alternatives in
|
179 | the YSH expression language, but they can still be used. See [YSH vs. Shell
|
180 | Idioms](idioms.html).
|
181 |
|
182 | Also related: [Known Differences Between OSH and Other
|
183 | Shells](known-differences.html).
|
184 |
|
185 | ## Appendix
|
186 |
|
187 | Here are some notable **non-breaking** changes.
|
188 |
|
189 | ### Shell Functions vs. Procs
|
190 |
|
191 | Procs have truly local variables like Python and JavaScript. There's no
|
192 | [dynamic scope]($xref:dynamic-scope) rule, as with shell functions.
|
193 |
|
194 | This is something to be aware of, but isn't technically a breakage because
|
195 | shell functions still work the same way in YSH.
|
196 |
|
197 | ### $EDITOR vs. ENV.EDITOR
|
198 |
|
199 | In YSH, env vars live in the [ENV][] dict. So instead of `$EDITOR`, you should
|
200 | use `$[ENV.EDITOR]`.
|
201 |
|
202 | But doesn't break when you `shopt --set ysh:upgrade`, only when you use
|
203 | `bin/ysh`.
|
204 |
|
205 | [ENV]: ref/chap-special-var.html#ENV
|
206 |
|
207 | ### Acknowledgments
|
208 |
|
209 | Thank you to `ca2013` for reviewing this doc.
|
210 |
|