| 1 | 
 | 
| 2 | #### case
 | 
| 3 | foo=a; case $foo in [0-9]) echo number;; [a-z]) echo letter;; esac
 | 
| 4 | ## stdout: letter
 | 
| 5 | 
 | 
| 6 | #### case in subshell
 | 
| 7 | # Hm this subhell has to know about the closing ) and stuff like that.
 | 
| 8 | # case_clause is a compound_command, which is a command.  And a subshell
 | 
| 9 | # takes a compound_list, which is a list of terms, which has and_ors in them
 | 
| 10 | # ... which eventually boils down to a command.
 | 
| 11 | echo $(foo=a; case $foo in [0-9]) echo number;; [a-z]) echo letter;; esac)
 | 
| 12 | ## stdout: letter
 | 
| 13 | 
 | 
| 14 | #### Command sub word part
 | 
| 15 | # "The token shall not be delimited by the end of the substitution."
 | 
| 16 | foo=FOO; echo $(echo $foo)bar$(echo $foo)
 | 
| 17 | ## stdout: FOObarFOO
 | 
| 18 | 
 | 
| 19 | #### Backtick
 | 
| 20 | foo=FOO; echo `echo $foo`bar`echo $foo`
 | 
| 21 | ## stdout: FOObarFOO
 | 
| 22 | 
 | 
| 23 | #### Backtick 2
 | 
| 24 | echo `echo -n l; echo -n s`
 | 
| 25 | ## stdout: ls
 | 
| 26 | 
 | 
| 27 | #### Nested backticks
 | 
| 28 | # Inner `` are escaped!  Not sure how to do triple..  Seems like an unlikely
 | 
| 29 | # use case.  Not sure if I even want to support this!
 | 
| 30 | echo X > $TMP/000000-first
 | 
| 31 | echo `\`echo -n l; echo -n s\` $TMP | grep 000000-first`
 | 
| 32 | ## stdout: 000000-first
 | 
| 33 | 
 | 
| 34 | #### Making command out of command sub should work
 | 
| 35 | # Works in bash and dash!
 | 
| 36 | $(echo ec)$(echo ho) split builtin
 | 
| 37 | ## stdout: split builtin
 | 
| 38 | 
 | 
| 39 | #### Making keyword out of command sub should NOT work
 | 
| 40 | $(echo f)$(echo or) i in a b c; do echo $i; done
 | 
| 41 | echo status=$?
 | 
| 42 | ## stdout-json: ""
 | 
| 43 | ## status: 2
 | 
| 44 | ## OK mksh status: 1
 | 
| 45 | 
 | 
| 46 | #### Command sub with here doc
 | 
| 47 | echo $(<<EOF tac
 | 
| 48 | one
 | 
| 49 | two
 | 
| 50 | EOF
 | 
| 51 | )
 | 
| 52 | ## stdout: two one
 | 
| 53 | 
 | 
| 54 | #### Here doc with pipeline
 | 
| 55 | <<EOF tac | tr '\n' 'X'
 | 
| 56 | one
 | 
| 57 | two
 | 
| 58 | EOF
 | 
| 59 | ## stdout-json: "twoXoneX"
 | 
| 60 | 
 | 
| 61 | #### Command Sub word split
 | 
| 62 | argv.py $(echo 'hi there') "$(echo 'hi there')"
 | 
| 63 | ## stdout: ['hi', 'there', 'hi there']
 | 
| 64 | 
 | 
| 65 | #### Command Sub trailing newline removed
 | 
| 66 | s=$(python2 -c 'print("ab\ncd\n")')
 | 
| 67 | argv.py "$s"
 | 
| 68 | ## stdout: ['ab\ncd']
 | 
| 69 | 
 | 
| 70 | #### Command Sub trailing whitespace not removed
 | 
| 71 | s=$(python2 -c 'print("ab\ncd\n ")')
 | 
| 72 | argv.py "$s"
 | 
| 73 | ## stdout: ['ab\ncd\n ']
 | 
| 74 | 
 | 
| 75 | #### Command Sub and exit code
 | 
| 76 | # A command resets the exit code, but an assignment doesn't.
 | 
| 77 | echo $(echo x; exit 33)
 | 
| 78 | echo $?
 | 
| 79 | x=$(echo x; exit 33)
 | 
| 80 | echo $?
 | 
| 81 | ## STDOUT:
 | 
| 82 | x
 | 
| 83 | 0
 | 
| 84 | 33
 | 
| 85 | ## END
 | 
| 86 | 
 | 
| 87 | #### Command Sub in local sets exit code
 | 
| 88 | # A command resets the exit code, but an assignment doesn't.
 | 
| 89 | f() {
 | 
| 90 |   echo $(echo x; exit 33)
 | 
| 91 |   echo $?
 | 
| 92 |   local x=$(echo x; exit 33)
 | 
| 93 |   echo $?
 | 
| 94 | }
 | 
| 95 | f
 | 
| 96 | ## STDOUT:
 | 
| 97 | x
 | 
| 98 | 0
 | 
| 99 | 0
 | 
| 100 | ## END
 | 
| 101 | 
 | 
| 102 | #### Double Quotes in Command Sub in Double Quotes
 | 
| 103 | # virtualenv's bin/activate uses this.
 | 
| 104 | # This is weird!  Double quotes within `` is different than double quotes
 | 
| 105 | # within $()!  All shells agree.
 | 
| 106 | # I think this is related to the nested backticks case!
 | 
| 107 | echo "x $(echo hi)"
 | 
| 108 | echo "x $(echo "hi")"
 | 
| 109 | echo "x $(echo \"hi\")"
 | 
| 110 | echo "x `echo hi`"
 | 
| 111 | echo "x `echo "hi"`"
 | 
| 112 | echo "x `echo \"hi\"`"
 | 
| 113 | ## STDOUT:
 | 
| 114 | x hi
 | 
| 115 | x hi
 | 
| 116 | x "hi"
 | 
| 117 | x hi
 | 
| 118 | x hi
 | 
| 119 | x hi
 | 
| 120 | ## END
 | 
| 121 | 
 | 
| 122 | #### Escaped quote in [[ ]]
 | 
| 123 | file=$TMP/command-sub-dbracket
 | 
| 124 | #rm -f $file
 | 
| 125 | echo "123 `[[ $(echo \\" > $file) ]]` 456";
 | 
| 126 | cat $file
 | 
| 127 | ## STDOUT:
 | 
| 128 | 123  456
 | 
| 129 | "
 | 
| 130 | ## END
 | 
| 131 | 
 | 
| 132 | #### Quoting " within ``
 | 
| 133 | echo 1 `echo \"`
 | 
| 134 | #echo 2 `echo \\"`
 | 
| 135 | #echo 3 `echo \\\"`
 | 
| 136 | #echo 4 `echo \\\\"`
 | 
| 137 | 
 | 
| 138 | ## STDOUT:
 | 
| 139 | 1 "
 | 
| 140 | ## END
 | 
| 141 | 
 | 
| 142 | #### Quoting $ within ``
 | 
| 143 | echo 1 `echo $`
 | 
| 144 | echo 2 `echo \$`
 | 
| 145 | echo 3 `echo \\$`
 | 
| 146 | echo 4 `echo \\\$`
 | 
| 147 | echo 5 `echo \\\\$`
 | 
| 148 | ## STDOUT:
 | 
| 149 | 1 $
 | 
| 150 | 2 $
 | 
| 151 | 3 $
 | 
| 152 | 4 $
 | 
| 153 | 5 \$
 | 
| 154 | ## END
 | 
| 155 | 
 | 
| 156 | #### Quoting $ within `` within double quotes
 | 
| 157 | echo "1 `echo $`"
 | 
| 158 | echo "2 `echo \$`"
 | 
| 159 | echo "3 `echo \\$`"
 | 
| 160 | echo "4 `echo \\\$`"
 | 
| 161 | echo "5 `echo \\\\$`"
 | 
| 162 | ## STDOUT:
 | 
| 163 | 1 $
 | 
| 164 | 2 $
 | 
| 165 | 3 $
 | 
| 166 | 4 $
 | 
| 167 | 5 \$
 | 
| 168 | ## END
 | 
| 169 | 
 | 
| 170 | #### Quoting \ within ``
 | 
| 171 | # You need FOUR backslashes to make a literal \.
 | 
| 172 | echo [1 `echo \ `]
 | 
| 173 | echo [2 `echo \\ `]
 | 
| 174 | echo [3 `echo \\\\ `]
 | 
| 175 | ## STDOUT:
 | 
| 176 | [1 ]
 | 
| 177 | [2 ]
 | 
| 178 | [3 \]
 | 
| 179 | ## END
 | 
| 180 | 
 | 
| 181 | #### Quoting \ within `` within double quotes
 | 
| 182 | echo "[1 `echo \ `]"
 | 
| 183 | echo "[2 `echo \\ `]"
 | 
| 184 | echo "[3 `echo \\\\ `]"
 | 
| 185 | ## STDOUT:
 | 
| 186 | [1  ]
 | 
| 187 | [2  ]
 | 
| 188 | [3 \]
 | 
| 189 | ## END
 | 
| 190 | 
 | 
| 191 | #### Quoting ( within ``
 | 
| 192 | echo 1 `echo \(`
 | 
| 193 | echo 2 `echo \\(`
 | 
| 194 | echo 3 `echo \\ \\(`
 | 
| 195 | ## STDOUT:
 | 
| 196 | 1 (
 | 
| 197 | 2 (
 | 
| 198 | 3 (
 | 
| 199 | ## END
 | 
| 200 | 
 | 
| 201 | #### Quoting ( within `` within double quotes
 | 
| 202 | echo "1 `echo \(`"
 | 
| 203 | echo "2 `echo \\(`"
 | 
| 204 | echo "3 `echo \\ \\(`"
 | 
| 205 | ## STDOUT:
 | 
| 206 | 1 (
 | 
| 207 | 2 (
 | 
| 208 | 3  (
 | 
| 209 | ## END
 | 
| 210 | 
 | 
| 211 | #### Quoting non-special characters within ``
 | 
| 212 | echo [1 `echo \z]`
 | 
| 213 | echo [2 `echo \\z]`
 | 
| 214 | echo [3 `echo \\\z]`
 | 
| 215 | echo [4 `echo \\\\z]`
 | 
| 216 | ## STDOUT:
 | 
| 217 | [1 z]
 | 
| 218 | [2 z]
 | 
| 219 | [3 \z]
 | 
| 220 | [4 \z]
 | 
| 221 | ## END
 | 
| 222 | 
 | 
| 223 | #### Quoting non-special characters within `` within double quotes
 | 
| 224 | echo "[1 `echo \z`]"
 | 
| 225 | echo "[2 `echo \\z`]"
 | 
| 226 | echo "[3 `echo \\\z`]"
 | 
| 227 | echo "[4 `echo \\\\z`]"
 | 
| 228 | ## STDOUT:
 | 
| 229 | [1 z]
 | 
| 230 | [2 z]
 | 
| 231 | [3 \z]
 | 
| 232 | [4 \z]
 | 
| 233 | ## END
 | 
| 234 | 
 | 
| 235 | #### Quoting double quotes within backticks
 | 
| 236 | echo \"foo\"   # for comparison
 | 
| 237 | echo `echo \"foo\"`
 | 
| 238 | echo `echo \\"foo\\"`
 | 
| 239 | ## STDOUT:
 | 
| 240 | "foo"
 | 
| 241 | "foo"
 | 
| 242 | "foo"
 | 
| 243 | ## END
 | 
| 244 | 
 | 
| 245 | #### More levels of double quotes in backticks
 | 
| 246 | # Shells don't agree here, some of them give you form feeds!
 | 
| 247 | # There are two levels of processing I don't understand.
 | 
| 248 | echo BUG
 | 
| 249 | exit
 | 
| 250 | echo `echo \\\"foo\\\"`
 | 
| 251 | echo `echo \\\\"foo\\\\"`
 | 
| 252 | echo `echo \\\\\"foo\\\\\"`
 | 
| 253 | ## BUG bash/dash/mksh/osh STDOUT:
 | 
| 254 | BUG
 | 
| 255 | ## END
 | 
| 256 | 
 | 
| 257 | #### Syntax errors with double quotes within backticks
 | 
| 258 | 
 | 
| 259 | # bash does print syntax errors but somehow it exits 0
 | 
| 260 | 
 | 
| 261 | $SH -c 'echo `echo "`'
 | 
| 262 | echo status=$?
 | 
| 263 | $SH -c 'echo `echo \\\\"`'
 | 
| 264 | echo status=$?
 | 
| 265 | 
 | 
| 266 | ## STDOUT:
 | 
| 267 | status=2
 | 
| 268 | status=2
 | 
| 269 | ## END
 | 
| 270 | ## OK mksh STDOUT:
 | 
| 271 | status=1
 | 
| 272 | status=1
 | 
| 273 | ## END
 | 
| 274 | ## OK bash stdout-json: "\nstatus=0\n\nstatus=0\n"
 | 
| 275 | 
 | 
| 276 | 
 | 
| 277 | #### Empty command sub $() (command::NoOp)
 | 
| 278 | 
 | 
| 279 | # IMPORTANT: catch assert() failure in child process!!!
 | 
| 280 | shopt -s command_sub_errexit
 | 
| 281 | 
 | 
| 282 | echo -$()- ".$()."
 | 
| 283 | ## STDOUT:
 | 
| 284 | -- ..
 | 
| 285 | ## END
 |