| 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 | ### Shell Functions vs. Procs
|
| 188 |
|
| 189 | Procs have truly local variables like Python and JavaScript. There's no
|
| 190 | [dynamic scope]($xref:dynamic-scope) rule, as with shell functions.
|
| 191 |
|
| 192 | This is something to be aware of, but isn't technically a breakage because
|
| 193 | shell functions still work the same way in YSH.
|
| 194 |
|
| 195 | ### Acknowledgments
|
| 196 |
|
| 197 | Thank you to `ca2013` for reviewing this doc.
|
| 198 |
|