| 1 | ---
 | 
| 2 | default_highlighter: oils-sh
 | 
| 3 | in_progress: true
 | 
| 4 | ---
 | 
| 5 | 
 | 
| 6 | Strings: Quotes, Interpolation, Escaping, and Buffers
 | 
| 7 | =====================================================
 | 
| 8 | 
 | 
| 9 | Strings are the most important data structure in shell.  YSH makes them easier
 | 
| 10 | and safer!
 | 
| 11 | 
 | 
| 12 | This doc addresses these questions:
 | 
| 13 | 
 | 
| 14 | - How do you write different kinds of strings in YSH programs?
 | 
| 15 | - How do they behave at runtime?  What are the common operations?
 | 
| 16 | - What are the recommended ways to use them?
 | 
| 17 | 
 | 
| 18 | Shell Features:
 | 
| 19 | 
 | 
| 20 | - Quotes (single or double quoted)
 | 
| 21 | - Interpolation aka substitution (variable, command, etc.)
 | 
| 22 | 
 | 
| 23 | YSH Features:
 | 
| 24 | 
 | 
| 25 | - Escaping for safety: `${x|html}`, etc.
 | 
| 26 | - Buffers for efficiency and readability: `${.myproc arg1}`, etc.
 | 
| 27 |   - (buffers are PHP-like)
 | 
| 28 | 
 | 
| 29 | <div id="toc">
 | 
| 30 | </div>
 | 
| 31 | 
 | 
| 32 | ## Summary
 | 
| 33 | 
 | 
| 34 | - YSH has three ways to write strings: single quoted, double quoted, and
 | 
| 35 |   C-style (which is also QSN-style).
 | 
| 36 | - Each of the three types has a multiline variant.  They are Python-style
 | 
| 37 |   triple-quoted, but they also strip leading space in an intelligent way.
 | 
| 38 | - TODO: Tagged strings, like `"<h2>$x</h2>"html`
 | 
| 39 | - TODO: For string safety, YSH adds the concept of "escapers" and interpolation
 | 
| 40 |   with `$[x]` (square brackets)
 | 
| 41 | - TODO: For convenience and performance, YSH adds buffers and *builtin
 | 
| 42 |   substitution*: `${.myproc arg1}`.
 | 
| 43 | 
 | 
| 44 | ### For Python/JS/C Users
 | 
| 45 | 
 | 
| 46 | - Single and double quotes are different.    Double quotes allow interpolation.
 | 
| 47 | - Neither style of string respects backslash escapes like `\n` for newline.
 | 
| 48 |   You have to use the third form.
 | 
| 49 | 
 | 
| 50 | ### For Shell Users
 | 
| 51 | 
 | 
| 52 | - YSH replaces here docs with Python-style triple-quoted strings.
 | 
| 53 | 
 | 
| 54 | Preferences:
 | 
| 55 | 
 | 
| 56 | - Unquoted strings (command mode only)
 | 
| 57 | - Single-quoted strings
 | 
| 58 |   - when you need to express special characters
 | 
| 59 |   - QSN
 | 
| 60 | - Double-quoted strings
 | 
| 61 |   - with `$[]` interpolation
 | 
| 62 |   - with `${}` interpolation
 | 
| 63 |   - with fast command sub `${.myproc arg1}
 | 
| 64 | 
 | 
| 65 | ### Quick Reference
 | 
| 66 | 
 | 
| 67 |     echo unquoted          # bare words are allowed in command mode
 | 
| 68 | 
 | 
| 69 |     echo 'with spaces'     # single quoted string
 | 
| 70 |     var s = 'with spaces'
 | 
| 71 | 
 | 
| 72 |     # Raw single quoted string, to emphasize literal backslashes
 | 
| 73 |     var s = r'C:\Program Files\'
 | 
| 74 | 
 | 
| 75 |     # C-escaped single quoted string
 | 
| 76 |     var line = $'foo\n'
 | 
| 77 | 
 | 
| 78 |     # double quoted with safe interpolation (TODO)
 | 
| 79 |     echo "<p>hello $[name]</p>"       # default_escaper must be set
 | 
| 80 |     echo "<p>hello ${name|html}</p>"  # explicit escaper
 | 
| 81 | 
 | 
| 82 |     # double quoted with unsafe interpolation
 | 
| 83 |     echo "hello $name"
 | 
| 84 |     echo "hello ${name}_suffix"       # braces delimit variable name
 | 
| 85 | 
 | 
| 86 |     echo $(date +%x)                  # command sub
 | 
| 87 | 
 | 
| 88 | Still TODO:
 | 
| 89 | 
 | 
| 90 |     echo ${.myproc arg1}
 | 
| 91 | 
 | 
| 92 |     cat <<< '''
 | 
| 93 |        one
 | 
| 94 |        two
 | 
| 95 |        '''
 | 
| 96 | 
 | 
| 97 |     cat <<< $'''
 | 
| 98 |        mu = \u{3bc}
 | 
| 99 |        nul = \x00
 | 
| 100 |        '''
 | 
| 101 | 
 | 
| 102 |     var s = """
 | 
| 103 |        multiline with ${vars}
 | 
| 104 |        $(date +%x)
 | 
| 105 |        ${.myproc arg1}
 | 
| 106 |        """
 | 
| 107 | 
 | 
| 108 | 
 | 
| 109 | ## Use Unquoted Strings in Command Mode
 | 
| 110 | 
 | 
| 111 | Shell is unique!  You don't have to quote strings.
 | 
| 112 | 
 | 
| 113 | - link: command vs. expression mode
 | 
| 114 | 
 | 
| 115 | and quoted strings in expression mode
 | 
| 116 | 
 | 
| 117 | ## Two Kinds of Single-Quoted Strings
 | 
| 118 | 
 | 
| 119 | ### Raw with `r'C:\Program Files\'`
 | 
| 120 | 
 | 
| 121 | - TODO: `parse_raw_strings`
 | 
| 122 | 
 | 
| 123 | ### C-Escaped With `$'foo\n'` 
 | 
| 124 | 
 | 
| 125 | - Use the [QSN]($xref) subset
 | 
| 126 | 
 | 
| 127 | ### QSN For *Data* Interchange
 | 
| 128 | 
 | 
| 129 | TODO: explain the difference.
 | 
| 130 | 
 | 
| 131 | This is different!  It's data and not code.  Analogy to JSON.
 | 
| 132 | 
 | 
| 133 | - When you want represent any string on a single line (filenames)
 | 
| 134 | - To make binary data readable
 | 
| 135 | - To display data in a terminal (protect against terminal codes)
 | 
| 136 | 
 | 
| 137 | ## Use Double-Quoted Strings For Interpolation
 | 
| 138 | 
 | 
| 139 | ### Implicit Safe Interpolation with `$[x]` (TODO)
 | 
| 140 | 
 | 
| 141 | - Use `$[x]` for safe interpolation
 | 
| 142 |   - Respects `shopt --set default_escaper`
 | 
| 143 | 
 | 
| 144 | ### Explicit Safe Interpolation With `${x|html}` (TODO)
 | 
| 145 | 
 | 
| 146 | - Use `${x|html}` for safe interpolation
 | 
| 147 | 
 | 
| 148 | Note you can have bugs if you use the wrong escaper!
 | 
| 149 | 
 | 
| 150 | ### Raw Interpolation with `$x` (may be unsafe)
 | 
| 151 | 
 | 
| 152 | - Use `$x` or `${x}`
 | 
| 153 |   - These are identical except for syntax
 | 
| 154 | - Useful for log messages, which aren't security sensitive
 | 
| 155 | 
 | 
| 156 | Note that you should **not** use `"${var}"` in YSH code.  Use `$var` or
 | 
| 157 | `${var}` because of simple word evaluation.
 | 
| 158 | 
 | 
| 159 | ### Command Sub `$(echo hi)` 
 | 
| 160 | 
 | 
| 161 | ### Fast Command Sub `${.myproc}` (stdout capture)
 | 
| 162 | 
 | 
| 163 | Note that only words are allowed here; not full commands.  Wrap other commands
 | 
| 164 | in a proc.
 | 
| 165 | 
 | 
| 166 | - Using `write_to_buffer`
 | 
| 167 | 
 | 
| 168 | TODO:
 | 
| 169 | 
 | 
| 170 |    echo ${.myproc foo|html}  # I think this should be supported
 | 
| 171 | 
 | 
| 172 | ## Escapers / Codecs (TODO)
 | 
| 173 | 
 | 
| 174 | For `${x|html}` and `${.myproc|html}`
 | 
| 175 | 
 | 
| 176 | TODO
 | 
| 177 | 
 | 
| 178 | - how to register them
 | 
| 179 | - wasm plugins?
 | 
| 180 | 
 | 
| 181 | ## Use Triple Quoted Strings Instead of Here Docs (TODO)
 | 
| 182 | 
 | 
| 183 | TODO
 | 
| 184 | 
 | 
| 185 | ## Concatenate With `"$str1$str2"`
 | 
| 186 | 
 | 
| 187 | Or `"${str1}${str2}"`
 | 
| 188 | 
 | 
| 189 | - is `s ++ t` valid?. It isn't necessary for strings and lists
 | 
| 190 |   - `:| @a @b |` is the same for lists
 | 
| 191 |   - does this Python syntax also work?  `[*a, *b]`
 | 
| 192 |   - Dicts: `{d, **e}` might be better
 | 
| 193 | 
 | 
| 194 | ### Avoid Concatenation in a Loop
 | 
| 195 | 
 | 
| 196 |     setvar s = "${s}${suffix}"
 | 
| 197 | 
 | 
| 198 | ## Append with Two Styles
 | 
| 199 | 
 | 
| 200 | Since there is no `++` operator, there is no `++=` operator.
 | 
| 201 | 
 | 
| 202 | ### `echo`, `printf`, `write`, and `${.myproc}` (`write_to_buffer`)
 | 
| 203 | 
 | 
| 204 | echo, printf, and write have their output captured.
 | 
| 205 | 
 | 
| 206 |     proc p(arg) {
 | 
| 207 |       ### A proc that has its output captured quickly.
 | 
| 208 | 
 | 
| 209 |       echo $arg
 | 
| 210 |       write two
 | 
| 211 | 
 | 
| 212 |       const x = 'three'
 | 
| 213 |       printf '%s\n' $x
 | 
| 214 | 
 | 
| 215 |       # newline for interactive testing, but not when captured
 | 
| 216 |       if ! shopt -q write_to_buffer {
 | 
| 217 |         echo  
 | 
| 218 |       }
 | 
| 219 |     }
 | 
| 220 | 
 | 
| 221 |     echo ${.p one}  # $'one\ntwo\nthree\n'
 | 
| 222 | 
 | 
| 223 | ### `append` and `join`
 | 
| 224 | 
 | 
| 225 |     var buf = :| |
 | 
| 226 |     append 'one ' (buf)
 | 
| 227 |     append $'two\n' (buf)
 | 
| 228 |     echo $[join(buf)]
 | 
| 229 | 
 | 
| 230 | ## Appendix A: Deprecated Shell Constructs
 | 
| 231 | 
 | 
| 232 | - here docs!
 | 
| 233 |   - Use tripled quoted strings.
 | 
| 234 | - Backticks for command sub
 | 
| 235 |   - Use `$(echo hi)`
 | 
| 236 | - Arithmetic substitution like `$((1 + 2))`
 | 
| 237 |   - Use YSH expressions: `$[1 + 2]`
 | 
| 238 | - `${x%%prefix}` and so forth
 | 
| 239 |   - Use builtin YSH functions (TODO)
 | 
| 240 | - Unused: bash `$""` for localization?
 | 
| 241 | 
 | 
| 242 | ## Appendix B: Related Documents
 | 
| 243 | 
 | 
| 244 | - Simple Word Eval: you don't need quoting as much
 | 
| 245 | - Expression Language
 | 
| 246 | - [QSN](qsn.html)
 |