1# Test parameter expansion. Phew. 2# (By the way, did I say "phew"?) 3 4%prep 5 6 mkdir parameter.tmp 7 8 cd parameter.tmp 9 10 touch boringfile evenmoreboringfile 11 12%test 13 14 foo='the first parameter' 15 bar='the second parameter' 16 print -l $foo ${bar} 170:Basic scalar parameter substitution 18>the first parameter 19>the second parameter 20 21 array1=(the first array) 22 array2=(the second array) 23 print -l $array1 ${array2} 240:Basic array parameter substitution 25>the 26>first 27>array 28>the 29>second 30>array 31 32 setopt ksharrays 33 print -l $array1 ${array2} 34 unsetopt ksharrays 350:Basic ksharray substitution 36>the 37>the 38 39 setopt shwordsplit 40 print -l $foo ${bar} 41 print -l ${==bar} 42 unsetopt shwordsplit 430:Basic shwordsplit option handling 44>the 45>first 46>parameter 47>the 48>second 49>parameter 50>the second parameter 51 52 print $+foo ${+foo} $+notappearinginthistest ${+notappearinginthistest} 530:$+... 54>1 1 0 0 55 56 x=() 57 print ${+x} ${+x[1]} ${+x[(r)foo]} ${+x[(r)bar]} 58 x=(foo) 59 print ${+x} ${+x[1]} ${+x[(r)foo]} ${+x[(r)bar]} 600:$+... with arrays 61>1 0 0 0 62>1 1 1 0 63 64 set1=set1v 65 null1= 66 print ${set1:-set1d} ${set1-set2d} ${null1:-null1d} ${null1-null2d} x 67 print ${unset1:-unset1d} ${unset1-unset2d} x 680:${...:-...} and ${...-...} 69>set1v set1v null1d x 70>unset1d unset2d x 71 72 set2=irrelevant 73 print ${set1:=set1d} ${set2::=set2d} 74 print $set2 75 wasnull1= 76 wasnull2= 77 print ${wasnull1=wasnull1d} ${wasnull2:=wasnull2d} 78 print $wasnull1 $wasnull2 790:${...:=...}, ${...::=...}, ${...=...} 80>set1v set2d 81>set2d 82>wasnull2d 83>wasnull2d 84 85 (print ${set1:?okhere}; print ${unset1:?exiting1}; print not reached;) 86 (print ${null1?okhere}; print ${null1:?exiting2}; print not reached;) 871:${...:?...}, ${...?...} 88>set1v 89> 90?(eval):1: unset1: exiting1 91?(eval):2: null1: exiting2 92 93 print ${set1:+word1} ${set1+word2} ${null1:+word3} ${null1+word4} 94 print ${unset1:+word5} ${unset1+word6} 950:${...:+...}, ${...+...} 96>word1 word2 word4 97> 98 99 str1='This is very boring indeed.' 100 print ${str1#*s} 101 print ${str1##*s} 102 print $str1##s 1030:${...#...}, ${...##...} 104> is very boring indeed. 105> very boring indeed. 106>This is very boring indeed.##s 107 108 str2='If you'\''re reading this you should go and fix some bugs instead.' 109 print ${str2%d*} 110 print ${str2%%d*} 1110:${...%...}, ${...%%...} 112>If you're reading this you should go and fix some bugs instea 113>If you're rea 114 115 str1='does match' 116 str2='does not match' 117 print ${str1:#does * match} 118 print ${str2:#does * match} 1190:${...:#...} 120>does match 121> 122 123 array1=(arthur boldly claws dogs every fight) 124 print ${array1:#[aeiou]*} 125 print ${(M)array1:#[aeiou]*} 1260:${...:#...}, ${(M)...:#...} with array 127>boldly claws dogs fight 128>arthur every 129 130 str1="$array1" 131 print ${str1/[aeiou]*g/a braw bricht moonlicht nicht the nic} 132 print ${(S)str1/[aeiou]*g/relishe} 1330:scalar ${.../.../...}, ${(S).../.../...} 134>a braw bricht moonlicht nicht the nicht 135>relishes every fight 136 137 print ${array1/[aeiou]*/Y} 138 print ${(S)array1/[aeiou]*/Y} 1390:array ${.../.../...}, ${(S).../.../...} 140>Y bY clY dY Y fY 141>Yrthur bYldly clYws dYgs Yvery fYght 142 143 str1='o this is so, so so very dull' 144 print ${str1//o*/Please no} 145 print ${(S)str1//o*/Please no} 1460:scalar ${...//.../...}, ${(S)...//.../...} 147>Please no 148>Please no this is sPlease no, sPlease no sPlease no very dull 149 150 print ${array1//[aeiou]*/Y} 151 print ${(S)array1//[aeiou]*/Y} 1520:array ${...//.../...}, ${(S)...//.../...} 153>Y bY clY dY Y fY 154>YrthYr bYldly clYws dYgs YvYry fYght 155 156 print ${array1:/[aeiou]*/expletive deleted} 1570:array ${...:/...} 158>expletive deleted boldly claws dogs expletive deleted fight 159 160 str1='a\string\with\backslashes' 161 str2='a/string/with/slashes' 162 print "${str1//\\/-}" 163 print ${str1//\\/-} 164 print "${str2//\//-}" 165 print ${str2//\//-} 1660:use of backslashes in //-substitutions 167>a-string-with-backslashes 168>a-string-with-backslashes 169>a-string-with-slashes 170>a-string-with-slashes 171 172 args=('one' '#foo' '(bar' "'three'" two) 173 mod=('#foo' '(bar' "'three'" sir_not_appearing_in_this_film) 174 print ${args:|mod} 175 print ${args:*mod} 176 print "${(@)args:|mod}" 177 print "${(@)args:*mod}" 178 args=(two words) 179 mod=('one word' 'two words') 180 print "${args:|mod}" 181 print "${args:*mod}" 182 scalar='two words' 183 print ${scalar:|mod} 184 print ${scalar:*mod} 185 print ${args:*nonexistent} 186 empty= 187 print ${args:*empty} 1880:"|" array exclusion and "*" array intersection 189>one two 190>#foo (bar 'three' 191>one two 192>#foo (bar 'three' 193> 194>two words 195> 196>two words 197> 198> 199 200 str1='twocubed' 201 array=(the number of protons in an oxygen nucleus) 202 print $#str1 ${#str1} "$#str1 ${#str1}" $#array ${#array} "$#array ${#array}" 2030:${#...}, $#... 204>8 8 8 8 8 8 8 8 205 206 set 1 2 3 4 5 6 7 8 9 207 print ${##} 208 set 1 2 3 4 5 6 7 8 9 10 209 print ${##} 210 print ${##""} 211 print ${##1} 212 print ${##2} 213 print ${###<->} # oh, for pete's sake... 2140:${##} is length of $#, and other tales of hash horror 215>1 216>2 217>10 218>0 219>10 220> 221 222 array=(once bitten twice shy) 223 print IF${array}THEN 224 print IF${^array}THEN 2250:basic ${^...} 226>IFonce bitten twice shyTHEN 227>IFonceTHEN IFbittenTHEN IFtwiceTHEN IFshyTHEN 228 229 # Quote ${array} here because {...,...} doesn't like unquoted spaces. 230 print IF{"${array}",THEN}ELSE 231 print IF{${^array},THEN}ELSE 2320:combined ${^...} and {...,...} 233>IFonce bitten twice shyELSE IFTHENELSE 234>IFonceELSE IFTHENELSE IFbittenELSE IFTHENELSE IFtwiceELSE IFTHENELSE IFshyELSE IFTHENELSE 235 236 str1='one word' 237 print -l $str1 ${=str1} "split ${=str1}wise" 2380:${=...} 239>one word 240>one 241>word 242>split one 243>wordwise 244 245 str1='*' 246 print $str1 ${~str1} $~str1 247 setopt globsubst 248 print $str1 249 unsetopt globsubst 2500:${~...} and globsubst 251>* boringfile evenmoreboringfile boringfile evenmoreboringfile 252>boringfile evenmoreboringfile 253 254# The following tests a bug where globsubst didn't preserve 255# backslashes when printing out the original string. 256 str1='\\*\\' 257 ( 258 setopt globsubst nonomatch 259 [[ \\\\ = $str1 ]] && print -r '\\ matched by' $str1 260 [[ \\foo\\ = $str1 ]] && print -r '\\foo matched by' $str1 261 [[ a\\b\\ = $str1 ]] || print -r 'a\\b not matched by' $str1 262 ) 2630:globsubst with backslashes 264>\\ matched by \\*\\ 265>\\foo matched by \\*\\ 266>a\\b not matched by \\*\\ 267 268 ( 269 setopt globsubst 270 foo="boring*" 271 print ${foo+$foo} 272 print ${foo+"$foo"} 273 print ${~foo+"$foo"} 274 ) 2750:globsubst together with nested quoted expansion 276>boringfile 277>boring* 278>boringfile 279 280 print -l "${$(print one word)}" "${=$(print two words)}" 2810:splitting of $(...) inside ${...} 282>one word 283>two 284>words 285 286 (setopt shwordsplit # ensure this doesn't get set in main shell... 287 test_splitting () 288 { 289 array="one two three" 290 for e in $array; do 291 echo "'$e'" 292 done 293 } 294 test_split_var= 295 echo _${test_split_var:=$(test_splitting)}_ 296 echo "_${test_split_var}_") 2970:SH_WORD_SPLIT inside $(...) inside ${...} 298>_'one' 'two' 'three'_ 299>_'one' 300>'two' 301>'three'_ 302 303 print -l "${(f)$(print first line\\nsecond line\\nthird line)}" 3040:${(f)$(...)} 305>first line 306>second line 307>third line 308 309 array1=( uno ) 310 print -l ${(A)newarray=splitting by numbers} 311 print -l ${(t)newarray} 312 print -l ${(A)=newarray::=splitting by spaces, actually} 313 print -l ${(t)newarray} 314 print -l ${(A)newarray::=$array1} 315 print -l ${(t)newarray} 316 print -l ${newarray::=$array1} 317 print -l ${(t)newarray} 318 print -l ${newarray::=$array2} 319 print -l ${(t)newarray} 3200:${(A)...=...}, ${(A)...::=...}, ${scalar=$array} 321>splitting by numbers 322>array 323>splitting 324>by 325>spaces, 326>actually 327>array 328>uno 329>array 330>uno 331>scalar 332>the second array 333>scalar 334 335 newarray=("split me" "split me" "I\'m yours") 336 print -l "${(@)newarray}" 3370:"${(@)...}" 338>split me 339>split me 340>I'm yours 341 342 foo='$(print Howzat usay)' 343 print -l ${(e)foo} 3440:${(e)...} 345>Howzat 346>usay 347 348 foo='`print Howzat usay`' 349 print -l ${(e)foo} 3500:Regress ${(e)...} with backticks (see zsh-workers/15871) 351>Howzat 352>usay 353 354 foo='\u65\123' 355 print -r ${(g:o:)foo} 356 foo='\u65\0123^X\C-x' 357 print -r ${(g::)foo} 358 foo='^X' 359 bar='\C-\130' 360 [[ ${(g:c:)foo} == ${(g:oe:)bar} ]] 361 echo $? 3620:${(g)...} 363>eS 364>eS^X\C-x 365>0 366 367 foo='I'\''m nearly out of my mind with tedium' 368 bar=foo 369 print ${(P)bar} 3700:${(P)...} 371>I'm nearly out of my mind with tedium 372#' deconfuse emacs 373 374 foo=(I could be watching that programme I recorded) 375 print ${(o)foo} 376 print ${(oi)foo} 377 print ${(O)foo} 378 print ${(Oi)foo} 3790:${(o)...}, ${(O)...} 380>I I be could programme recorded that watching 381>be could I I programme recorded that watching 382>watching that recorded programme could be I I 383>watching that recorded programme I I could be 384 385 foo=(yOU KNOW, THE ONE WITH wILLIAM dALRYMPLE) 386 bar=(doing that tour of India.) 387 print ${(L)foo} 388 print ${(U)bar} 3890:${(L)...}, ${(U)...} 390>you know, the one with william dalrymple 391>DOING THAT TOUR OF INDIA. 392 393 foo='instead here I am stuck by the computer' 394 print ${(C)foo} 3950:${(C)...} 396>Instead Here I Am Stuck By The Computer 397 398 foo=$'\x7f\x00' 399 print ${(V)foo} 4000:${(V)...} 401>^?^@ 402 403 foo='playing '\''stupid'\'' "games" \w\i\t\h $quoting.' 404 print -r ${(q)foo} 405 print -r ${(qq)foo} 406 print -r ${(qqq)foo} 407 print -r ${(qqqq)foo} 408 print -r ${(q-)foo} 4090:${(q...)...} 410>playing\ \'stupid\'\ \"games\"\ \\w\\i\\t\\h\ \$quoting. 411>'playing '\''stupid'\'' "games" \w\i\t\h $quoting.' 412>"playing 'stupid' \"games\" \\w\\i\\t\\h \$quoting." 413>$'playing \'stupid\' "games" \\w\\i\\t\\h $quoting.' 414>'playing '\'stupid\'' "games" \w\i\t\h $quoting.' 415 416 x=( a '' '\b' 'c d' '$e' ) 417 print -r ${(q)x} 418 print -r ${(q-)x} 4190:Another ${(q...)...} test 420>a '' \\b c\ d \$e 421>a '' '\b' 'c d' '$e' 422 423 print -r -- ${(q-):-foo} 424 print -r -- ${(q-):-foo bar} 425 print -r -- ${(q-):-"*(.)"} 426 print -r -- ${(q-):-"wow 'this is cool' or is it?"} 427 print -r -- ${(q-):-"no-it's-not"} 4280:${(q-)...} minimal single quoting 429>foo 430>'foo bar' 431>'*(.)' 432>'wow '\''this is cool'\'' or is it?' 433>no-it\'s-not 434 435 foo="'and now' \"even the pubs\" \\a\\r\\e shut." 436 print -r ${(Q)foo} 4370:${(Q)...} 438>and now even the pubs are shut. 439 440 foo="X$'\x41'$'\x42'Y" 441 print -r ${(Q)foo} 4420:${(Q)...} with handling of $'...' 443>XABY 444 445 # The following may look a bit random. 446 # For the split we are checking that anything that 447 # would normally be followed by a different word has 448 # an argument break after it and anything that wouldn't doesn't. 449 # For the (Q) we are simply checking that nothing disappears 450 # in the parsing. 451 foo='<five> {six} (seven) >eight< }nine{ |forty-two| $many$ )ten( more' 452 array=(${(z)foo}) 453 print -l ${(Q)array} 4540:${(z)...} and ${(Q)...} for some hard to parse cases 455>< 456>five 457>> 458>{six} 459>( 460>seven 461>) 462>> 463>eight 464>< 465>}nine{ 466>| 467>forty-two 468>| 469>$many$ 470>) 471>ten( more 472 473 strings=( 474 'foo=(1 2 3)' 475 '(( 3 + 1 == 8 / 2 ))' 476 'for (( i = 1 ; i < 10 ; i++ ))' 477 '((0.25542 * 60) - 15)*60' 478 ) 479 for string in $strings; do 480 array=(${(z)string}) 481 for (( i = 1; i <= ${#array}; i++ )); do 482 print -r -- "${i}:${array[i]}:" 483 done 484 done 4850:Some syntactical expressions that are hard to split into words with (z). 486>1:foo=(: 487>2:1: 488>3:2: 489>4:3: 490>5:): 491>1:(( 3 + 1 == 8 / 2 )): 492>1:for: 493>2:((: 494# Leading whitespace is removed, because the word proper hasn't started; 495# trailing whitespace is left because the word is terminated by the 496# semicolon or double parentheses. Bit confusing but sort of consistent. 497>3:i = 1 ;: 498>4:i < 10 ;: 499>5:i++ : 500>6:)): 501# This one needs resolving between a math expression and 502# a command, which causes interesting effects internally. 503>1:(: 504>2:(: 505>3:0.25542: 506>4:*: 507>5:60: 508>6:): 509>7:-: 510>8:15: 511>9:): 512>10:*60: 513 514 515 line=$'A line with # someone\'s comment\nanother line # (1 more\nanother one' 516 print "*** Normal ***" 517 print -l ${(z)line} 518 print "*** Kept ***" 519 print -l ${(Z+c+)line} 520 print "*** Removed ***" 521 print -l ${(Z+C+)line} 5220:Comments with (z) 523>*** Normal *** 524>A 525>line 526>with 527># 528>someone's comment 529>another line # (1 more 530>another one 531>*** Kept *** 532>A 533>line 534>with 535># someone's comment 536>; 537>another 538>line 539># (1 more 540>; 541>another 542>one 543>*** Removed *** 544>A 545>line 546>with 547>; 548>another 549>line 550>; 551>another 552>one 553 554 line='with comment # at the end' 555 print -l ${(Z+C+)line} 5560:Test we don't get an additional newline token 557>with 558>comment 559 560 line=$'echo one\necho two # with a comment\necho three' 561 print -l ${(Z+nc+)line} 5620:Treating zplit newlines as ordinary whitespace 563>echo 564>one 565>echo 566>two 567># with a comment 568>echo 569>three 570 571 psvar=(dog) 572 setopt promptsubst 573 foo='It shouldn'\''t $(happen) to a %1v.' 574 bar='But `echo what can you do\?`' 575 print -r ${(%)foo} 576 print -r ${(%%)bar} 5770:${(%)...} 578>It shouldn't $(happen) to a dog. 579>But what can you do? 580 581 foo='unmatched "' 582 print ${(QX)foo} 5831:${(QX)...} 584?(eval):2: unmatched " 585# " deconfuse emacs 586 587 array=(characters in an array) 588 print ${(c)#array} 5890:${(c)#...} 590>22 591 592 print ${(w)#array} 593 str='colon::bolon::solon' 594 print ${(ws.:.)#str} 595 print ${(Ws.:.)#str} 5960:${(w)...}, ${(W)...} 597>4 598>3 599>5 600 601 typeset -A assoc 602 assoc=(key1 val1 key2 val2) 603 print ${(o)assoc} 604 print ${(ok)assoc} 605 print ${(ov)assoc} 606 print ${(okv)assoc} 6070:${(k)...}, ${(v)...} 608>val1 val2 609>key1 key2 610>val1 val2 611>key1 key2 val1 val2 612 613 word="obfuscatory" 614 print !${(l.16.)word}! +${(r.16.)word}+ 6150:simple padding 616>! obfuscatory! +obfuscatory + 617 618 foo=(resulting words uproariously padded) 619 print ${(pl.10..\x22..X.)foo} 6200:${(pl...)...} 621>Xresulting """"Xwords roariously """Xpadded 622#" deconfuse emacs 623 624 print ${(l.5..X.r.5..Y.)foo} 625 print ${(l.6..X.r.4..Y.)foo} 626 print ${(l.7..X.r.3..Y.)foo} 627 print ${(l.6..X..A.r.6..Y..B.)foo} 628 print ${(l.6..X..AROOGA.r.6..Y..BARSOOM.)foo} 6290:simultaneous left and right padding 630>Xresulting XXXwordsYY proariousl XXpaddedYY 631>XXresultin XXXXwordsY uproarious XXXpaddedY 632>XXXresulti XXXXXwords Xuproariou XXXXpadded 633>XAresultingB XXXAwordsBYY uproariously XXApaddedBYY 634>GAresultingB OOGAwordsBAR uproariously OGApaddedBAR 635 636 foo=(why in goodness name am I doing this) 637 print ${(r.5..!..?.)foo} 6380:${(r...)...} 639>why?! in?!! goodn name? am?!! I?!!! doing this? 640 641 array=(I\'m simply putting a brave face on) 642 print ${(j:--:)array} 6430:${(j)...} 644>I'm--simply--putting--a--brave--face--on 645 646 print ${(F)array} 6470:${(F)...} 648>I'm 649>simply 650>putting 651>a 652>brave 653>face 654>on 655 656 string='zometimez zis getz zplit on a z' 657 print -l ${(s?z?)string} 6580:${(s...)...} 659>ometime 660> 661>is get 662> 663>plit on a 664 665 str=s 666 arr=(a) 667 typeset -A ass 668 ass=(a a) 669 integer i 670 float f 671 print ${(t)str} ${(t)arr} ${(t)ass} ${(t)i} ${(t)f} 6720:${(t)...} 673>scalar array association-local integer-local float-local 674 675 # it's not quite clear that these are actually right unless you know 676 # the algorithm: search along the string for the point at which the 677 # first (last) match occurs, for ## (%%), then take the shortest possible 678 # version of that for # (%). it's as good a definition as anything. 679 string='where is the white windmill, whispered walter wisely' 680 print ${(S)string#h*e} 681 print ${(S)string##h*e} 682 print ${(S)string%h*e} 683 print ${(S)string%%h*e} 6840:${(S)...#...} etc. 685>wre is the white windmill, whispered walter wisely 686>wly 687>where is the white windmill, wred walter wisely 688>where is the white windmill, wly 689 690 setopt extendedglob 691 print ${(SI:1:)string##w[^[:space:]]# } 692 print ${(SI:1+1:)string##w[^[:space:]]# } 693 print ${(SI:1+1+1:)string##w[^[:space:]]# } 694 print ${(SI:1+1+1+1:)string##w[^[:space:]]# } 6950:${(I:...:)...} 696>is the white windmill, whispered walter wisely 697>where is the windmill, whispered walter wisely 698>where is the white whispered walter wisely 699>where is the white windmill, walter wisely 700 701 print ${(MSI:1:)string##w[^[:space:]]# } 7020:${(M...)...} 703>where 704 705 print ${(R)string//w[a-z]# #} 7060:${(R)...} 707>is the , 708 709 # This (1) doesn't work with // or / 710 # (2) perhaps ought to be 18, to be consistent with normal zsh 711 # substring indexing and with backreferences. 712 print ${(BES)string##white} 7130:${(BE...)...} 714>14 19 715 716 print ${(NS)string##white} 7170:${(N)...} 718>5 719 720 string='abcdefghijklmnopqrstuvwxyz' 721 print ${${string%[aeiou]*}/(#m)?(#e)/${(U)MATCH}} 7220:Rule 1: Nested substitutions 723>abcdefghijklmnopqrsT 724 725 array=(et Swann avec cette muflerie intermittente) 726 string="qui reparaissait chez lui" 727 print ${array[4,5]} 728 print ${array[4,5][1]} 729 print ${array[4,5][1][2,3]} 730 print ${string[4,5]} 731 print ${string[4,5][1]} 7320:Rule 2: Parameter subscripting 733>cette muflerie 734>cette 735>et 736> r 737> 738 739 foo=stringalongamax 740 print ${${(P)foo[1,6]}[1,3]} 7410:Rule 3: Parameter Name Replacement 742>qui 743 744 print "${array[5,6]}" 745 print "${(j.:.)array[1,2]}" 7460:Rule 4: Double-Quoted Joining 747>muflerie intermittente 748>et:Swann 749 750 print "${${array}[5,7]}" 751 print "${${(@)array}[1,2]}" 7520:Rule 5: Nested Subscripting 753>wan 754>et Swann 755 756 print "${${(@)array}[1,2]#?}" 757 print "${(@)${(@)array}[1,2]#?}" 7580:Rule 6: Modifiers 759>t Swann 760>t wann 761 762 array=(she sells z shells by the z shore) 763 (IFS='+'; print ${(s.s.)array}) 7640:Rule 7: Forced Joining, and 8: Forced splitting 765>he+ ell +z+ hell +by+the+z+ hore 766 767 setopt shwordsplit 768 string='another poxy boring string' 769 print -l ${${string}/o/ } 770 unsetopt shwordsplit 7710:Rule 9: Shell Word Splitting 772>an 773>ther 774>p 775>xy 776>b 777>ring 778>string 779 780 setopt nonomatch 781 foo='b* e*' 782 print ${(e)~foo} 783 print ${(e)~=foo} 7840:Rule 10: Re-Evaluation 785>b* e* 786>boringfile evenmoreboringfile 787 788 # ${bar} -> $bar here would yield "bad substitution". 789 bar=confinement 790 print ${(el.20..X.)${bar}} 7910:Rule 11: Padding 792>XXXXXXXXXconfinement 793 794 foo=(bar baz) 795 bar=(ax1 bx1) 796 print "${(@)${foo}[1]}" 797 print "${${(@)foo}[1]}" 798 print -l ${(s/x/)bar} 799 print -l ${(j/x/s/x/)bar} 800 print -l ${(s/x/)bar%%1*} 8010:Examples in manual on parameter expansion 802>b 803>bar 804>a 805>1 b 806>1 807>a 808>1 809>b 810>1 811>a 812> b 813 814 set If "this test fails" "we have broken" the shell again 815 print -l ${1+"$@"} 8160:Regression test of ${1+"$@"} bug 817>If 818>this test fails 819>we have broken 820>the 821>shell 822>again 823 824 set If "this test fails" "we have broken" the shell again 825 print -l "${(A)foo::=$@}" 826 print -l ${(t)foo} 827 print -l $foo 8280:Regression test of "${(A)foo=$@}" bug 829>If this test fails we have broken the shell again 830>array 831>If 832>this test fails 833>we have broken 834>the 835>shell 836>again 837 838 local sure_that='sure that' varieties_of='varieties of' one=1 two=2 839 extra=(5 4 3) 840 unset foo 841 set Make $sure_that "this test keeps" on 'preserving all' "$varieties_of" quoted whitespace 842 print -l ${=1+"$@"} 843 print -l ${(A)=foo=Make $sure_that "this test keeps" on 'preserving all' "$varieties_of" quoted whitespace} 844 print ${(t)foo} 845 print -l ${=1+$one $two} 846 print -l ${1+$extra$two$one} 8470:Regression test of ${=1+"$@"} bug and some related expansions 848>Make 849>sure that 850>this test keeps 851>on 852>preserving all 853>varieties of 854>quoted 855>whitespace 856>Make 857>sure 858>that 859>this test keeps 860>on 861>preserving all 862>varieties of 863>quoted 864>whitespace 865>array 866>1 867>2 868>5 869>4 870>321 871 872 splitfn() { 873 emulate -L sh 874 local HOME="/differs from/bash" foo='1 2' bar='3 4' 875 print -l ${1:-~} 876 touch has\ space 877 print -l ${1:-*[ ]*} 878 print -l ${1:-*[\ ]*} 879 print -l ${1:-*} 880 print -l ${1:-"$foo" $bar} 881 print -l ${==1:-$foo $bar} 882 rm has\ space 883 } 884 splitfn 8850:More bourne-shell-compatible nested word-splitting with wildcards and ~ 886>/differs from/bash 887>*[ 888>]* 889>has space 890>boringfile 891>evenmoreboringfile 892>has space 893>1 2 894>3 895>4 896>1 2 3 4 897 898 splitfn() { 899 local IFS=.- 900 local foo=1-2.3-4 901 # 902 print "Called with argument '$1'" 903 print "No quotes" 904 print -l ${=1:-1-2.3-4} ${=1:-$foo} 905 print "With quotes on default argument only" 906 print -l ${=1:-"1-2.3-4"} ${=1:-"$foo"} 907 } 908 print 'Using "="' 909 splitfn 910 splitfn 5.6-7.8 911 # 912 splitfn() { 913 emulate -L zsh 914 setopt shwordsplit 915 local IFS=.- 916 local foo=1-2.3-4 917 # 918 print "Called with argument '$1'" 919 print "No quotes" 920 print -l ${1:-1-2.3-4} ${1:-$foo} 921 print "With quotes on default argument only" 922 print -l ${1:-"1-2.3-4"} ${1:-"$foo"} 923 } 924 print Using shwordsplit 925 splitfn 926 splitfn 5.6-7.8 9270:Test of nested word splitting with and without quotes 928>Using "=" 929>Called with argument '' 930>No quotes 931>1 932>2 933>3 934>4 935>1 936>2 937>3 938>4 939>With quotes on default argument only 940>1-2.3-4 941>1-2.3-4 942>Called with argument '5.6-7.8' 943>No quotes 944>5 945>6 946>7 947>8 948>5 949>6 950>7 951>8 952>With quotes on default argument only 953>5 954>6 955>7 956>8 957>5 958>6 959>7 960>8 961>Using shwordsplit 962>Called with argument '' 963>No quotes 964>1 965>2 966>3 967>4 968>1 969>2 970>3 971>4 972>With quotes on default argument only 973>1-2.3-4 974>1-2.3-4 975>Called with argument '5.6-7.8' 976>No quotes 977>5 978>6 979>7 980>8 981>5 982>6 983>7 984>8 985>With quotes on default argument only 986>5 987>6 988>7 989>8 990>5 991>6 992>7 993>8 994 995# Tests a long-standing bug with joining on metafied characters in IFS 996 (array=(one two three) 997 IFS=$'\0' 998 foo="$array" 999 for (( i = 1; i <= ${#foo}; i++ )); do 1000 char=${foo[i]} 1001 print $(( #char )) 1002 done) 10030:Joining with NULL character from IFS 1004>111 1005>110 1006>101 1007>0 1008>116 1009>119 1010>111 1011>0 1012>116 1013>104 1014>114 1015>101 1016>101 1017 1018 unset SHLVL 1019 (( SHLVL++ )) 1020 print $SHLVL 10210:Unsetting and recreation of numerical special parameters 1022>1 1023 1024 unset manpath 1025 print $+MANPATH 1026 manpath=(/here /there) 1027 print $MANPATH 1028 unset MANPATH 1029 print $+manpath 1030 MANPATH=/elsewhere:/somewhere 1031 print $manpath 10320:Unsetting and recreation of tied special parameters 1033>0 1034>/here:/there 1035>0 1036>/elsewhere /somewhere 1037 1038 local STRING=a:b 1039 typeset -T STRING string 1040 print $STRING $string 1041 unset STRING 1042 set -A string x y z 1043 print $STRING $string 1044 STRING=a:b 1045 typeset -T STRING string 1046 print $STRING $string 1047 unset STRING 1048 set -A string x y z 1049 print $STRING $string 1050 STRING=a:b 1051 typeset -T STRING string 1052 print $STRING $string 1053 unset string 1054 STRING=x:y:z 1055 print $STRING $string 1056 STRING=a:b 1057 typeset -T STRING string 1058 print $STRING $string 1059 unset string 1060 STRING=x:y:z 1061 print $STRING $string 10620:Unsetting and recreation of tied normal parameters 1063>a:b a b 1064>x y z 1065>a:b a b 1066>x y z 1067>a:b a b 1068>x:y:z 1069>a:b a b 1070>x:y:z 1071 1072 string='look for a match in here' 1073 if [[ ${string%%(#b)(match)*} = "look for a " ]]; then 1074 print $match[1] $mbegin[1] $mend[1] $string[$mbegin[1],$mend[1]] 1075 print $#match $#mbegin $#mend 1076 else 1077 print That didn\'t work. 1078 fi 10790:Parameters associated with backreferences 1080>match 12 16 match 1081>1 1 1 1082#' deconfuse emacs 1083 1084 string='and look for a MATCH in here' 1085 if [[ ${(S)string%%(#m)M*H} = "and look for a in here" ]]; then 1086 print $MATCH $MBEGIN $MEND $string[$MBEGIN,$MEND] 1087 print $#MATCH 1088 else 1089 print Oh, dear. Back to the drawing board. 1090 fi 10910:Parameters associated with (#m) flag 1092>MATCH 16 20 MATCH 1093>5 1094 1095 string='this is a string' 1096 print ${string//(#m)s/$MATCH $MBEGIN $MEND} 10970:(#m) flag with pure string 1098>this 4 4 is 7 7 a s 11 11tring 1099 1100 print ${${~:-*}//(#m)*/$MATCH=$MATCH} 11010:(#m) flag with tokenized input 1102>*=* 1103 1104 print -l JAMES${(u)${=:-$(echo yes yes)}}JOYCE 1105 print -l JAMES${(u)${=:-$(echo yes yes she said yes i will yes)}}JOYCE 11060:Bug with (u) flag reducing arrays to one element 1107>JAMESyesJOYCE 1108>JAMESyes 1109>she 1110>said 1111>i 1112>willJOYCE 1113 1114 print -l JAMES${(u)${=:-$(echo yes yes she said yes i will yes she said she will and yes she did yes)}}JOYCE 11150:New hash seive unique algorithm for arrays of more than 10 elements 1116>JAMESyes 1117>she 1118>said 1119>i 1120>will 1121>and 1122>didJOYCE 1123 1124 foo= 1125 print "${${foo}/?*/replacement}" 11260:Quoted zero-length strings are handled properly 1127> 1128 1129 file=aleftkept 1130 print ${file//(#b)(*)left/${match/a/andsome}} 1131 print ${file//(#b)(*)left/${match//a/andsome}} 11320:Substitutions where $match is itself substituted in the replacement 1133>andsomekept 1134>andsomekept 1135 1136 file=/one/two/three/four 1137 print ${file:fh} 1138 print ${file:F.1.h} 1139 print ${file:F+2+h} 1140 print ${file:F(3)h} 1141 print ${file:F<4>h} 1142 print ${file:F{5}h} 11430:Modifiers with repetition 1144>/ 1145>/one/two/three 1146>/one/two 1147>/one 1148>/ 1149>/ 1150 1151 baz=foo/bar 1152 zab=oof+rab 1153 print ${baz:s/\//+/} 1154 print "${baz:s/\//+/}" 1155 print ${zab:s/+/\//} 1156 print "${zab:s/+/\//}" 11570:Quoting of separator in substitution modifier 1158>foo+bar 1159>foo+bar 1160>oof/rab 1161>oof/rab 1162 1163 bsbs='X\\\\Y' 1164 print -r -- ${bsbs:s/\\/\\/} 1165 print -r -- "${bsbs:s/\\/\\/}" 1166 print -r -- ${bsbs:s/\\\\/\\\\/} 1167 print -r -- "${bsbs:s/\\\\/\\\\/}" 1168 print -r -- ${bsbs:gs/\\/\\/} 1169 print -r -- "${bsbs:gs/\\/\\/}" 1170 print -r -- ${bsbs:gs/\\\\/\\\\/} 1171 print -r -- "${bsbs:gs/\\\\/\\\\/}" 11720:Handling of backslashed backslashes in substitution modifier 1173>X\\\\Y 1174>X\\\\Y 1175>X\\\\Y 1176>X\\\\Y 1177>X\\\\Y 1178>X\\\\Y 1179>X\\\\Y 1180>X\\\\Y 1181 1182 print -r ${${:-one/two}:s,/,X&Y,} 1183 print -r ${${:-one/two}:s,/,X\&Y,} 1184 print -r ${${:-one/two}:s,/,X\\&Y,} 1185 print -r "${${:-one/two}:s,/,X&Y,}" 1186 print -r "${${:-one/two}:s,/,X\&Y,}" 1187 print -r "${${:-one/two}:s,/,X\\&Y,}" 11880:Quoting of ampersand in substitution modifier RHS 1189>oneX/Ytwo 1190>oneX&Ytwo 1191>oneX\/Ytwo 1192>oneX/Ytwo 1193>oneX&Ytwo 1194>oneX\/Ytwo 1195 1196 nully=($'a\0c' $'a\0b\0b' $'a\0b\0a' $'a\0b\0' $'a\0b' $'a\0' $'a') 1197 for string in ${(o)nully}; do 1198 for (( i = 1; i <= ${#string}; i++ )); do 1199 foo=$string[i] 1200 printf "%02x" $(( #foo )) 1201 done 1202 print 1203 done 12040:Sorting arrays with embedded nulls 1205>61 1206>6100 1207>610062 1208>61006200 1209>6100620061 1210>6100620062 1211>610063 1212 1213 array=(X) 1214 patterns=("*X*" "spong" "a[b") 1215 for pat in $patterns; do 1216 print A${array[(r)$pat]}B C${array[(I)$pat]}D 1217 done 12180:Bad patterns should never match array elements 1219>AXB C1D 1220>AB C0D 1221>AB C0D 1222 1223 foo=(a6 a117 a17 b6 b117 b17) 1224 print ${(n)foo} 1225 print ${(On)foo} 12260:Numeric sorting 1227>a6 a17 a117 b6 b17 b117 1228>b117 b17 b6 a117 a17 a6 1229 1230 x=sprodj 1231 x[-10]=scrumf 1232 print $x 12330:Out of range negative scalar subscripts 1234>scrumfsprodj 1235 1236 a=(some sunny day) 1237 a[-10]=(we\'ll meet again) 1238 print -l $a 12390:Out of range negative array subscripts 1240>we'll 1241>meet 1242>again 1243>some 1244>sunny 1245>day 1246 1247# ' emacs likes this close quote 1248 1249 a=(sping spang spong bumble) 1250 print ${a[(i)spong]} 1251 print ${a[(i)spung]} 1252 print ${a[(ib.1.)spong]} 1253 print ${a[(ib.4.)spong]} 1254 print ${a[(ib.10.)spong]} 12550:In and out of range reverse matched indices without and with b: arrays 1256>3 1257>5 1258>3 1259>5 1260>5 1261 1262 a="thrimblewuddlefrong" 1263 print ${a[(i)w]} 1264 print ${a[(i)x]} 1265 print ${a[(ib.3.)w]} 1266 print ${a[(ib.10.)w]} 1267 print ${a[(ib.30.)w]} 12680:In and out of range reverse matched indices without and with b: strings 1269>9 1270>20 1271>9 1272>20 1273>20 1274 1275 foo="line:with::missing::fields:in:it" 1276 print -l ${(s.:.)foo} 12770:Removal of empty fields in unquoted splitting 1278>line 1279>with 1280>missing 1281>fields 1282>in 1283>it 1284 1285 foo="line:with::missing::fields:in:it" 1286 print -l "${(s.:.)foo}" 12870:Hacky removal of empty fields in quoted splitting with no "@" 1288>line 1289>with 1290>missing 1291>fields 1292>in 1293>it 1294 1295 foo="line:with::missing::fields:in:it:" 1296 print -l "${(@s.:.)foo}" 12970:Retention of empty fields in quoted splitting with "@" 1298>line 1299>with 1300> 1301>missing 1302> 1303>fields 1304>in 1305>it 1306> 1307 1308 str=abcd 1309 print -l ${(s..)str} 1310 print -l "${(s..)str}" 13110:splitting of strings into characters 1312>a 1313>b 1314>c 1315>d 1316>a 1317>b 1318>c 1319>d 1320 1321 array=('%' '$' 'j' '*' '$foo') 1322 print ${array[(i)*]} "${array[(i)*]}" 1323 print ${array[(ie)*]} "${array[(ie)*]}" 1324 key='$foo' 1325 print ${array[(ie)$key]} "${array[(ie)$key]}" 1326 key='*' 1327 print ${array[(ie)$key]} "${array[(ie)$key]}" 13280:Matching array indices with and without quoting 1329>1 1 1330>4 4 1331>5 5 1332>4 4 1333 1334# Ordering of associative arrays is arbitrary, so we need to use 1335# patterns that only match one element. 1336 typeset -A assoc_r 1337 assoc_r=(star '*' of '*this*' and '!that!' or '(the|other)') 1338 print ${(kv)assoc_r[(re)*]} 1339 print ${(kv)assoc_r[(re)*this*]} 1340 print ${(kv)assoc_r[(re)!that!]} 1341 print ${(kv)assoc_r[(re)(the|other)]} 1342 print ${(kv)assoc_r[(r)*at*]} 1343 print ${(kv)assoc_r[(r)*(ywis|bliss|kiss|miss|this)*]} 1344 print ${(kv)assoc_r[(r)(this|that|\(the\|other\))]} 13450:Reverse subscripting associative arrays with literal matching 1346>star * 1347>of *this* 1348>and !that! 1349>or (the|other) 1350>and !that! 1351>of *this* 1352>or (the|other) 1353 1354 print $ZSH_SUBSHELL 1355 (print $ZSH_SUBSHELL) 1356 ( (print $ZSH_SUBSHELL) ) 1357 ( (print $ZSH_SUBSHELL); print $ZSH_SUBSHELL ) 1358 print $(print $ZSH_SUBSHELL) 1359 cat =(print $ZSH_SUBSHELL) 13600:ZSH_SUBSHELL 1361>0 1362>1 1363>2 1364>2 1365>1 1366>1 1367>1 1368 1369 foo=("|" "?") 1370 [[ "|" = ${(j.|.)foo} ]] && print yes || print no 1371 [[ "|" = ${(j.|.)~foo} ]] && print yes || print no 1372 [[ "|" = ${(~j.|.)foo} ]] && print yes || print no 1373 [[ "|" = ${(~~j.|.)foo} ]] && print yes || print no 1374 [[ "|" = ${(j.|.~)foo} ]] && print yes || print no 1375 [[ "x" = ${(j.|.)foo} ]] && print yes || print no 1376 [[ "x" = ${(j.|.)~foo} ]] && print yes || print no 1377 [[ "x" = ${(~j.|.)foo} ]] && print yes || print no 1378 [[ "x" = ${(~~j.|.)foo} ]] && print yes || print no 1379 [[ "x" = ${(j.|.~)foo} ]] && print yes || print no 13800:GLOBSUBST only on parameter substitution arguments 1381>no 1382>yes 1383>yes 1384>no 1385>no 1386>no 1387>yes 1388>no 1389>no 1390>no 1391 1392 rcexbug() { 1393 emulate -L zsh 1394 setopt rcexpandparam 1395 local -A hash 1396 local -a full empty 1397 full=(X x) 1398 hash=(X x) 1399 print ORDINARY ARRAYS 1400 : The following behaves as documented in zshoptions 1401 print FULL expand=$full 1402 : Empty arrays remove the adjacent argument 1403 print EMPTY expand=$empty 1404 print ASSOCIATIVE ARRAY 1405 print Subscript flags returning many values 1406 print FOUND key=$hash[(I)X] val=$hash[(R)x] 1407 : This should behave like $empty, and does 1408 print LOST key=$hash[(I)y] val=$hash[(R)Y] 1409 print Subscript flags returning single values 1410 : Doc says "substitutes ... empty string" 1411 : so must not behave like an empty array 1412 print STRING key=$hash[(i)y] val=$hash[(r)Y] 1413 } 1414 rcexbug 14150:Lookup failures on elements of arrays with RC_EXPAND_PARAM 1416>ORDINARY ARRAYS 1417>FULL expand=X expand=x 1418>EMPTY 1419>ASSOCIATIVE ARRAY 1420>Subscript flags returning many values 1421>FOUND key=X val=x 1422>LOST 1423>Subscript flags returning single values 1424>STRING key= val= 1425 1426 print $zsh_eval_context[1] 1427 [[ $ZSH_EVAL_CONTEXT = ${(j.:.)zsh_eval_context} ]] || print Not equal! 1428 (( icontext = ${#zsh_eval_context} + 1 )) 1429 contextfn() { print $(print $zsh_eval_context[icontext,-1]); } 1430 contextfn 14310:$ZSH_EVAL_CONTEXT and $zsh_eval_context 1432>toplevel 1433>shfunc cmdsubst 1434 1435 foo="123456789" 1436 print ${foo:3} 1437 print ${foo: 1 + 3} 1438 print ${foo:$(( 2 + 3))} 1439 print ${foo:$(echo 3 + 3)} 1440 print ${foo:3:1} 1441 print ${foo: 1 + 3:(4-2)/2} 1442 print ${foo:$(( 2 + 3)):$(( 7 - 6 ))} 1443 print ${foo:$(echo 3 + 3):`echo 4 - 3`} 1444 print ${foo: -1} 1445 print ${foo: -10} 1446 print ${foo:5:-2} 14470:Bash-style offsets, scalar 1448>456789 1449>56789 1450>6789 1451>789 1452>4 1453>5 1454>6 1455>7 1456>9 1457>123456789 1458>67 1459 1460 foo=(1 2 3 4 5 6 7 8 9) 1461 print ${foo:3} 1462 print ${foo: 1 + 3} 1463 print ${foo:$(( 2 + 3))} 1464 print ${foo:$(echo 3 + 3)} 1465 print ${foo:3:1} 1466 print ${foo: 1 + 3:(4-2)/2} 1467 print ${foo:$(( 2 + 3)):$(( 7 - 6 ))} 1468 print ${foo:$(echo 3 + 3):`echo 4 - 3`} 1469 print ${foo: -1} 1470 print ${foo: -10} 1471 print ${foo:5:-2} 14720:Bash-style offsets, array 1473>4 5 6 7 8 9 1474>5 6 7 8 9 1475>6 7 8 9 1476>7 8 9 1477>4 1478>5 1479>6 1480>7 1481>9 1482>1 2 3 4 5 6 7 8 9 1483>6 7 1484 1485 testfn() { 1486 emulate -L sh 1487 set -A foo 1 2 3 1488 set -- 1 2 3 1489 str=abc 1490 echo ${foo[*]:0:1} 1491 echo ${foo[*]:1:1} 1492 echo ${foo[*]: -1:1} 1493 : 1494 echo ${*:0:1} 1495 echo ${*:1:1} 1496 echo ${*: -1:1} 1497 : 1498 echo ${str:0:1} 1499 echo ${str:1:1} 1500 echo ${str: -1:1} 1501 } 1502 testfn 15030:Bash-style offsets, Bourne-style indexing 1504>1 1505>2 1506>3 1507>testfn 1508>1 1509>3 1510>a 1511>b 1512>c 1513 1514 printf "%n" '[0]' 15151:Regression test for identifier test 1516?(eval):1: not an identifier: [0] 1517 1518 str=rts 1519 print ${str:0:} 15201:Regression test for missing length after offset 1521?(eval):2: unrecognized modifier 1522 1523 foo="123456789" 1524 print ${foo:5:-6} 15251:Regression test for total length < 0 in string 1526?(eval):2: substring expression: 3 < 5 1527 1528 foo=(1 2 3 4 5 6 7 8 9) 1529 print ${foo:5:-6} 15301:Regression test for total length < 0 in array 1531?(eval):2: substring expression: 3 < 5 1532 1533 foo=(${(0)"$(print -n)"}) 1534 print ${#foo} 15350:Nularg removed from split empty string 1536>0 1537 1538 (set -- a b c 1539 setopt shwordsplit 1540 IFS= 1541 print -rl "$*" 1542 unset IFS 1543 print -rl "$*") 15440:Regression test for shwordsplit with null or unset IFS and quoted array 1545>abc 1546>a b c 1547 1548 foo= 1549 print ${foo:wq} 1550 print ${:wq} 15510:Empty parameter shouldn't cause modifiers to crash the shell 1552> 1553> 1554 1555# This used to cause uncontrolled behaviour, but at best 1556# you got the wrong output so the check is worth it. 1557 args() { print $#; } 1558 args ${:*} 1559 args ${:|} 15600:Intersection and disjunction with empty parameters 1561>0 1562>0 1563