1 #
2 # Alias is in POSIX.
3 #
4 # http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_03_01
5 #
6 # Bash is the only one that doesn't support aliases by default!
7
8 #### Usage of builtins
9 shopt -s expand_aliases || true
10 alias -- foo=echo
11 echo status=$?
12 foo x
13 unalias -- foo
14 foo x
15 ## status: 127
16 ## STDOUT:
17 status=0
18 x
19 ## END
20 # dash doesn't accept --
21 ## BUG dash STDOUT:
22 status=1
23 x
24 ## END
25
26 #### Basic alias
27 shopt -s expand_aliases # bash requires this
28 alias hi='echo hello world'
29 hi || echo 'should not run this'
30 echo hi # second word is not
31 'hi' || echo 'expected failure'
32 ## STDOUT:
33 hello world
34 hi
35 expected failure
36 ## END
37
38 #### define and use alias on a single line
39 shopt -s expand_aliases
40 alias e=echo; e one # this is not alias-expanded because we parse lines at once
41 e two; e three
42 ## STDOUT:
43 two
44 three
45 ## END
46
47 #### alias can override builtin
48 shopt -s expand_aliases
49 alias echo='echo foo'
50 echo bar
51 ## stdout: foo bar
52
53 #### defining multiple aliases, then unalias
54 shopt -s expand_aliases # bash requires this
55 x=x
56 y=y
57 alias echo-x='echo $x' echo-y='echo $y'
58 echo status=$?
59 echo-x X
60 echo-y Y
61 unalias echo-x echo-y
62 echo status=$?
63 echo-x X || echo undefined
64 echo-y Y || echo undefined
65 ## STDOUT:
66 status=0
67 x X
68 y Y
69 status=0
70 undefined
71 undefined
72 ## END
73
74 #### alias not defined
75 alias e='echo' nonexistentZ
76 echo status=$?
77 ## STDOUT:
78 status=1
79 ## END
80 ## OK mksh STDOUT:
81 nonexistentZ alias not found
82 status=1
83 ## END
84
85 #### unalias not defined
86 alias e=echo ll='ls -l'
87 unalias e nonexistentZ ll
88 echo status=$?
89 ## STDOUT:
90 status=1
91 ## END
92
93 #### listing given aliases
94 alias e=echo ll='ls -l'
95 alias e ll
96 ## STDOUT:
97 alias e='echo'
98 alias ll='ls -l'
99 ## END
100 ## OK mksh/zsh STDOUT:
101 e=echo
102 ll='ls -l'
103 ## END
104 ## OK dash STDOUT:
105 e='echo'
106 ll='ls -l'
107 ## END
108
109 #### alias without args lists all aliases
110 alias ex=exit ll='ls -l'
111 alias | grep -E 'ex=|ll=' # need to grep because mksh/zsh have builtin aliases
112 echo status=$?
113 ## STDOUT:
114 alias ex='exit'
115 alias ll='ls -l'
116 status=0
117 ## END
118 ## OK dash STDOUT:
119 ex='exit'
120 ll='ls -l'
121 status=0
122 ## END
123 ## OK mksh/zsh STDOUT:
124 ex=exit
125 ll='ls -l'
126 status=0
127 ## END
128
129 #### unalias without args is a usage error
130 unalias
131 echo status=$?
132 ## stdout: status=2
133 ## BUG mksh/dash stdout: status=0
134 ## BUG zsh stdout: status=1
135
136 #### alias with trailing space causes alias expansion on second word
137 shopt -s expand_aliases # bash requires this
138
139 alias hi='echo hello world '
140 alias punct='!!!'
141
142 hi punct
143
144 alias hi='echo hello world' # No trailing space
145
146 hi punct
147
148 ## STDOUT:
149 hello world !!!
150 hello world punct
151 ## END
152
153 #### Recursive alias expansion of first word
154 shopt -s expand_aliases # bash requires this
155 alias hi='e_ hello world'
156 alias e_='echo __'
157 hi # first hi is expanded to echo hello world; then echo is expanded. gah.
158 ## STDOUT:
159 __ hello world
160 ## END
161
162 #### Recursive alias expansion of SECOND word
163 shopt -s expand_aliases # bash requires this
164 alias one='ONE '
165 alias two='TWO '
166 alias e_='echo one '
167 e_ two hello world
168 ## STDOUT:
169 one TWO hello world
170 ## END
171
172 #### Expansion of alias with variable
173 shopt -s expand_aliases # bash requires this
174 x=x
175 alias echo-x='echo $x' # nothing is evaluated here
176 x=y
177 echo-x hi
178 ## STDOUT:
179 y hi
180 ## END
181
182 #### Alias must be an unquoted word, no expansions allowed
183 shopt -s expand_aliases # bash requires this
184 alias echo_alias_='echo'
185 cmd=echo_alias_
186 echo_alias_ X # this works
187 $cmd X # this fails because it's quoted
188 echo status=$?
189 ## STDOUT:
190 X
191 status=127
192 ## END
193
194 #### first and second word are the same alias, but no trailing space
195 shopt -s expand_aliases # bash requires this
196 x=x
197 alias echo-x='echo $x' # nothing is evaluated here
198 echo-x echo-x
199 ## STDOUT:
200 x echo-x
201 ## END
202
203 #### first and second word are the same alias, with trailing space
204 shopt -s expand_aliases # bash requires this
205 x=x
206 alias echo-x='echo $x ' # nothing is evaluated here
207 echo-x echo-x
208 ## STDOUT:
209 x echo x
210 ## END
211
212 #### Invalid syntax of alias
213 shopt -s expand_aliases # bash requires this
214 alias echo_alias_= 'echo --; echo' # bad space here
215 echo_alias_ x
216 ## status: 127
217
218 #### Dynamic alias definition
219 shopt -s expand_aliases # bash requires this
220 x=x
221 name='echo_alias_'
222 val='=echo'
223 alias "$name$val"
224 echo_alias_ X
225 ## stdout: X
226
227 #### Alias name with punctuation
228 # NOTE: / is not OK in bash, but OK in other shells. Must less restrictive
229 # than var names.
230 shopt -s expand_aliases # bash requires this
231 alias e_+.~x='echo'
232 e_+.~x X
233 ## stdout: X
234
235 #### Syntax error after expansion
236 shopt -s expand_aliases # bash requires this
237 alias e_=';; oops'
238 e_ x
239 ## status: 2
240 ## OK mksh/zsh status: 1
241
242 #### Loop split across alias and arg works
243 shopt -s expand_aliases # bash requires this
244 alias e_='for i in 1 2 3; do echo $i;'
245 e_ done
246 ## STDOUT:
247 1
248 2
249 3
250 ## END
251
252 #### Loop split across alias in another way
253 shopt -s expand_aliases
254 alias e_='for i in 1 2 3; do echo '
255 e_ $i; done
256 ## STDOUT:
257 1
258 2
259 3
260 ## END
261 ## OK osh stdout-json: ""
262 ## OK osh status: 2
263
264 #### Loop split across both iterative and recursive aliases
265 shopt -s expand_aliases # bash requires this
266 alias FOR1='for '
267 alias FOR2='FOR1 '
268 alias eye1='i '
269 alias eye2='eye1 '
270 alias IN='in '
271 alias onetwo='$one "2" ' # NOTE: this does NOT work in any shell except bash.
272 one=1
273 FOR2 eye2 IN onetwo 3; do echo $i; done
274 ## STDOUT:
275 1
276 2
277 3
278 ## END
279 ## OK osh stdout-json: ""
280 ## OK osh status: 2
281 ## BUG zsh stdout-json: ""
282
283 #### Alias with a quote in the middle is a syntax error
284 shopt -s expand_aliases
285 alias e_='echo "'
286 var=x
287 e_ '${var}"'
288 ## status: 2
289 ## OK mksh/zsh status: 1
290
291 #### Alias with internal newlines
292 shopt -s expand_aliases
293 alias e_='echo 1
294 echo 2
295 echo 3'
296 var='echo foo'
297 e_ ${var}
298 ## STDOUT:
299 1
300 2
301 3 echo foo
302 ## END
303
304 #### Alias trailing newline
305 shopt -s expand_aliases
306 alias e_='echo 1
307 echo 2
308 echo 3
309 '
310 var='echo foo'
311 e_ ${var}
312 ## STDOUT:
313 1
314 2
315 3
316 foo
317 ## END
318 ## OK zsh STDOUT:
319 1
320 2
321 3
322 ## END
323 ## OK zsh status: 127
324
325 #### Two aliases in pipeline
326 shopt -s expand_aliases
327 alias SEQ='seq '
328 alias THREE='3 '
329 alias WC='wc '
330 SEQ THREE | WC -l
331 ## stdout: 3
332
333 #### Alias not respected inside $()
334 # This could be parsed correctly, but it is only defined in a child process.
335 shopt -s expand_aliases
336 echo $(alias sayhi='echo hello')
337 sayhi
338 ## status: 127
339
340 #### Alias can be defined and used on a single line
341 shopt -s expand_aliases
342 alias sayhi='echo hello'; sayhi same line
343 sayhi other line
344 ## STDOUT:
345 hello other line
346 ## END
347
348 #### Alias is respected inside eval
349 shopt -s expand_aliases
350 eval "alias sayhi='echo hello'
351 sayhi inside"
352 sayhi outside
353 ## STDOUT:
354 hello inside
355 hello outside
356 ## END
357 ## BUG zsh STDOUT:
358 hello outside
359 ## END
360
361 #### alias with redirects works
362 shopt -s expand_aliases
363 alias e_=echo
364 >$TMP/alias1.txt e_ 1
365 e_ >$TMP/alias2.txt 2
366 e_ 3 >$TMP/alias3.txt
367 cat $TMP/alias1.txt $TMP/alias2.txt $TMP/alias3.txt
368 ## STDOUT:
369 1
370 2
371 3
372 ## END
373
374 #### alias with environment bindings works
375 shopt -s expand_aliases
376 alias p_=printenv.py
377 FOO=1 printenv.py FOO
378 FOO=2 p_ FOO
379 ## STDOUT:
380 1
381 2
382 ## END
383
384 #### alias with line continuation in the middle
385 shopt -s expand_aliases
386 alias e_='echo '
387 alias one='ONE '
388 alias two='TWO '
389 alias three='THREE' # no trailing space
390 e_ one \
391 two one \
392 two three two \
393 one
394 ## stdout: ONE TWO ONE TWO THREE two one
395
396 #### alias for left brace
397 shopt -s expand_aliases
398 alias LEFT='{'
399 LEFT echo one; echo two; }
400 ## STDOUT:
401 one
402 two
403 ## END
404 ## OK osh stdout-json: ""
405 ## OK osh status: 2
406
407 #### alias for left paren
408 shopt -s expand_aliases
409 alias LEFT='('
410 LEFT echo one; echo two )
411 ## STDOUT:
412 one
413 two
414 ## END
415 ## OK osh stdout-json: ""
416 ## OK osh status: 2
417
418 #### alias used in subshell and command sub
419 # This spec seems to be contradictoary?
420 # http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_03_01
421 # "When used as specified by this volume of POSIX.1-2017, alias definitions
422 # shall not be inherited by separate invocations of the shell or by the utility
423 # execution environments invoked by the shell; see Shell Execution
424 # Environment."
425 shopt -s expand_aliases
426 alias echo_='echo [ '
427 ( echo_ subshell; )
428 echo $(echo_ commandsub)
429 ## STDOUT:
430 [ subshell
431 [ commandsub
432 ## END
433
434 #### alias used in here doc
435 shopt -s expand_aliases
436 alias echo_='echo [ '
437 cat <<EOF
438 $(echo_ ])
439 EOF
440 ## STDOUT:
441 [ ]
442 ## END
443
444 #### here doc inside alias
445 shopt -s expand_aliases
446 alias c='cat <<EOF
447 $(echo hi)
448 EOF
449 '
450 c
451 ## STDOUT:
452 hi
453 ## END
454 ## BUG bash stdout-json: ""
455 ## BUG bash status: 127
456
457 #### Corner case: alias inside LHS array arithmetic expression
458 shopt -s expand_aliases
459 alias zero='echo 0'
460 a[$(zero)]=ZERO
461 a[1]=ONE
462 argv.py "${a[@]}"
463 ## STDOUT:
464 ['ZERO', 'ONE']
465 ## END
466 ## N-I dash stdout-json: ""
467 ## N-I dash status: 2
468 ## N-I zsh stdout-json: ""
469 ## N-I zsh status: 1
470
471 #### Alias that is pipeline
472 shopt -s expand_aliases
473 alias t1='echo hi|wc -c'
474 t1
475 ## STDOUT:
476 3
477 ## END
478
479 #### Alias that is && || ;
480 shopt -s expand_aliases
481 alias t1='echo one && echo two && echo 3 | wc -l;
482 echo four'
483 t1
484 ## STDOUT:
485 one
486 two
487 1
488 four
489 ## END
490
491 #### Alias and command sub (bug regression)
492 cd $TMP
493 shopt -s expand_aliases
494 echo foo bar > tmp.txt
495 alias a=argv.py
496 a `cat tmp.txt`
497 ## stdout: ['foo', 'bar']
498
499 #### Alias and arithmetic
500 shopt -s expand_aliases
501 alias a=argv.py
502 a $((1 + 2))
503 ## stdout: ['3']
504
505 #### Alias and PS4
506 # dash enters an infinite loop!
507 case $SH in
508 dash)
509 exit 1
510 ;;
511 esac
512
513 set -x
514 PS4='+$(echo trace) '
515 shopt -s expand_aliases
516 alias a=argv.py
517 a foo bar
518 ## stdout: ['foo', 'bar']
519 ## BUG dash status: 1
520 ## BUG dash stdout-json: ""
521
522 #### alias with keywords
523 # from issue #299
524 shopt -s expand_aliases
525 alias a=
526
527 # both of these fail to parse in OSH
528 # this is because of our cleaner evaluation model
529
530 a (( var = 0 ))
531 #a case x in x) true;; esac
532
533 echo done
534 ## stdout: done
535 ## OK osh status: 2
536 ## OK osh stdout-json: ""