diff options
Diffstat (limited to 'dotfiles/system/.zsh/modules/Test/D04parameter.ztst')
| -rw-r--r-- | dotfiles/system/.zsh/modules/Test/D04parameter.ztst | 2058 | 
1 files changed, 2058 insertions, 0 deletions
| diff --git a/dotfiles/system/.zsh/modules/Test/D04parameter.ztst b/dotfiles/system/.zsh/modules/Test/D04parameter.ztst new file mode 100644 index 0000000..9128c3c --- /dev/null +++ b/dotfiles/system/.zsh/modules/Test/D04parameter.ztst @@ -0,0 +1,2058 @@ +# Test parameter expansion.  Phew. +# (By the way, did I say "phew"?) + +%prep + +  mkdir parameter.tmp + +  cd parameter.tmp + +  touch boringfile evenmoreboringfile + +%test + +  foo='the first parameter' +  bar='the second parameter' +  print -l $foo ${bar} +0:Basic scalar parameter substitution +>the first parameter +>the second parameter + +  array1=(the first array) +  array2=(the second array) +  print -l $array1 ${array2} +0:Basic array parameter substitution +>the +>first +>array +>the +>second +>array + +  setopt ksharrays +  print -l $array1 ${array2} +  unsetopt ksharrays +0:Basic ksharray substitution +>the +>the + +  setopt shwordsplit +  print -l $foo ${bar} +  print -l ${==bar} +  unsetopt shwordsplit +0:Basic shwordsplit option handling +>the +>first +>parameter +>the +>second +>parameter +>the second parameter + +  print $+foo ${+foo} $+notappearinginthistest ${+notappearinginthistest} +0:$+... +>1 1 0 0 + +  x=() +  print ${+x} ${+x[1]} ${+x[(r)foo]} ${+x[(r)bar]} +  x=(foo) +  print ${+x} ${+x[1]} ${+x[(r)foo]} ${+x[(r)bar]} +0:$+... with arrays +>1 0 0 0 +>1 1 1 0 + +  set1=set1v +  null1= +  print ${set1:-set1d} ${set1-set2d} ${null1:-null1d} ${null1-null2d} x +  print ${unset1:-unset1d} ${unset1-unset2d} x +0:${...:-...} and ${...-...} +>set1v set1v null1d x +>unset1d unset2d x + +  set2=irrelevant +  print ${set1:=set1d} ${set2::=set2d} +  print $set2 +  wasnull1= +  wasnull2= +  print ${wasnull1=wasnull1d} ${wasnull2:=wasnull2d} +  print $wasnull1 $wasnull2 +0:${...:=...}, ${...::=...}, ${...=...} +>set1v set2d +>set2d +>wasnull2d +>wasnull2d + +  unset array +  print ${#${(A)=array=word}} +0:${#${(A)=array=word}} counts array elements +>1 + +  (print ${set1:?okhere}; print ${unset1:?exiting1}; print not reached;) +  (print ${null1?okhere}; print ${null1:?exiting2}; print not reached;) +1:${...:?...}, ${...?...} +>set1v +> +?(eval):1: unset1: exiting1 +?(eval):2: null1: exiting2 + +  PROMPT="" $ZTST_testdir/../Src/zsh -fis <<<' +  unsetopt PROMPT_SP +  PS1="" PS2="" PS3="" PS4="" RPS1="" RPS2="" +  exec 2>&1 +  foo() { +      print ${1:?no arguments given} +      print not reached +  } +  foo +  print reached +  ' 2>/dev/null +0:interactive shell returns to top level on ${...?...} error +*>*foo:1: 1: no arguments given +>reached + +  print ${set1:+word1} ${set1+word2} ${null1:+word3} ${null1+word4} +  print ${unset1:+word5} ${unset1+word6} +0:${...:+...}, ${...+...} +>word1 word2 word4 +> + +  str1='This is very boring indeed.' +  print ${str1#*s} +  print ${str1##*s} +  print $str1##s +0:${...#...}, ${...##...} +> is very boring indeed. +> very boring indeed. +>This is very boring indeed.##s + +  str2='If you'\''re reading this you should go and fix some bugs instead.' +  print ${str2%d*} +  print ${str2%%d*} +0:${...%...}, ${...%%...} +>If you're reading this you should go and fix some bugs instea +>If you're rea + +  str1='does match' +  str2='does not match' +  print ${str1:#does * match} +  print ${str2:#does * match} +0:${...:#...} +>does match +> + +  array1=(arthur boldly claws dogs every fight) +  print ${array1:#[aeiou]*} +  print ${(M)array1:#[aeiou]*} +0:${...:#...}, ${(M)...:#...} with array +>boldly claws dogs fight +>arthur every + +  str1="$array1" +  print ${str1/[aeiou]*g/a braw bricht moonlicht nicht the nic} +  print ${(S)str1/[aeiou]*g/relishe} +0:scalar ${.../.../...}, ${(S).../.../...} +>a braw bricht moonlicht nicht the nicht +>relishes every fight + +  print ${array1/[aeiou]*/Y} +  print ${(S)array1/[aeiou]*/Y} +0:array ${.../.../...}, ${(S).../.../...} +>Y bY clY dY Y fY +>Yrthur bYldly clYws dYgs Yvery fYght + +  str1='o this is so, so so very dull' +  print ${str1//o*/Please no} +  print ${(S)str1//o*/Please no} +0:scalar ${...//.../...}, ${(S)...//.../...} +>Please no +>Please no this is sPlease no, sPlease no sPlease no very dull + +  print ${array1//[aeiou]*/Y} +  print ${(S)array1//[aeiou]*/Y} +0:array ${...//.../...}, ${(S)...//.../...} +>Y bY clY dY Y fY +>YrthYr bYldly clYws dYgs YvYry fYght + +  print ${array1:/[aeiou]*/expletive deleted} +0:array ${...:/...} +>expletive deleted boldly claws dogs expletive deleted fight + +  str1='a\string\with\backslashes' +  str2='a/string/with/slashes' +  print "${str1//\\/-}" +  print ${str1//\\/-} +  print "${str2//\//-}" +  print ${str2//\//-} +0:use of backslashes in //-substitutions +>a-string-with-backslashes +>a-string-with-backslashes +>a-string-with-slashes +>a-string-with-slashes + +  args=('one' '#foo' '(bar' "'three'" two) +  mod=('#foo' '(bar' "'three'" sir_not_appearing_in_this_film) +  print ${args:|mod} +  print ${args:*mod} +  print "${(@)args:|mod}" +  print "${(@)args:*mod}" +  args=(two words) +  mod=('one word' 'two words') +  print "${args:|mod}" +  print "${args:*mod}" +  scalar='two words' +  print ${scalar:|mod} +  print ${scalar:*mod} +  print ${args:*nonexistent} +  empty= +  print ${args:*empty} +0:"|" array exclusion and "*" array intersection +>one two +>#foo (bar 'three' +>one two +>#foo (bar 'three' +> +>two words +> +>two words +> +> + +  str1='twocubed' +  array=(the number of protons in an oxygen nucleus) +  print $#str1 ${#str1} "$#str1 ${#str1}" $#array ${#array} "$#array ${#array}" +0:${#...}, $#... +>8 8 8 8 8 8 8 8 + +  set 1 2 3 4 5 6 7 8 9 +  print ${##} +  set 1 2 3 4 5 6 7 8 9 10 +  print ${##} +  print ${##""} +  print ${##1} +  print ${##2} +  print ${###<->} # oh, for pete's sake... +0:${##} is length of $#, and other tales of hash horror +>1 +>2 +>10 +>0 +>10 +> + +  array=(once bitten twice shy) +  print IF${array}THEN +  print IF${^array}THEN +0:basic ${^...} +>IFonce bitten twice shyTHEN +>IFonceTHEN IFbittenTHEN IFtwiceTHEN IFshyTHEN + +  # Quote ${array} here because {...,...} doesn't like unquoted spaces. +  print IF{"${array}",THEN}ELSE +  print IF{${^array},THEN}ELSE +0:combined ${^...} and {...,...} +>IFonce bitten twice shyELSE IFTHENELSE +>IFonceELSE IFTHENELSE IFbittenELSE IFTHENELSE IFtwiceELSE IFTHENELSE IFshyELSE IFTHENELSE + +  str1='one word' +  print -l $str1 ${=str1} "split ${=str1}wise" +0:${=...} +>one word +>one +>word +>split one +>wordwise + +  str1='*' +  print $str1 ${~str1} $~str1 +  setopt globsubst +  print $str1 +  unsetopt globsubst +0:${~...} and globsubst +>* boringfile evenmoreboringfile boringfile evenmoreboringfile +>boringfile evenmoreboringfile + +# The following tests a bug where globsubst didn't preserve +# backslashes when printing out the original string. +  str1='\\*\\' +  ( +  setopt globsubst nonomatch +  [[ \\\\ = $str1 ]] && print -r '\\ matched by' $str1 +  [[ \\foo\\ = $str1 ]] && print -r '\\foo matched by' $str1 +  [[ a\\b\\ = $str1 ]] || print -r 'a\\b not matched by' $str1 +  ) +0:globsubst with backslashes +>\\ matched by \\*\\ +>\\foo matched by \\*\\ +>a\\b not matched by \\*\\ + +  ( +    setopt globsubst +    foo="boring*" +    print ${foo+$foo} +    print ${foo+"$foo"} +    print ${~foo+"$foo"} +  ) +0:globsubst together with nested quoted expansion +>boringfile +>boring* +>boringfile + +  print -l "${$(print one word)}" "${=$(print two words)}" +0:splitting of $(...) inside ${...} +>one word +>two +>words + +  (setopt shwordsplit # ensure this doesn't get set in main shell... +  test_splitting () +  { +    array="one two three" +    for e in $array; do +      echo "'$e'" +    done +  } +  test_split_var= +  echo _${test_split_var:=$(test_splitting)}_ +  echo "_${test_split_var}_") +0:SH_WORD_SPLIT inside $(...) inside ${...} +>_'one' 'two' 'three'_ +>_'one' +>'two' +>'three'_ + +  print -l "${(f)$(print first line\\nsecond line\\nthird line)}" +0:${(f)$(...)} +>first line +>second line +>third line + +  array1=( uno ) +  print -l ${(A)newarray=splitting by numbers} +  print -l ${(t)newarray} +  print -l ${(A)=newarray::=splitting by spaces, actually} +  print -l ${(t)newarray} +  print -l ${(A)newarray::=$array1} +  print -l ${(t)newarray} +  print -l ${newarray::=$array1} +  print -l ${(t)newarray} +  print -l ${newarray::=$array2} +  print -l ${(t)newarray} +0:${(A)...=...}, ${(A)...::=...}, ${scalar=$array} +>splitting by numbers +>array +>splitting +>by +>spaces, +>actually +>array +>uno +>array +>uno +>scalar +>the second array +>scalar + +  newarray=("split me" "split me" "I\'m yours") +  print -l "${(@)newarray}" +0:"${(@)...}" +>split me +>split me +>I'm yours + +  foo='$(print Howzat usay)' +  print -l ${(e)foo} +0:${(e)...} +>Howzat +>usay + +  foo='`print Howzat usay`' +  print -l ${(e)foo} +0:Regress ${(e)...} with backticks (see zsh-workers/15871) +>Howzat +>usay + +  foo='\u65\123' +  print -r ${(g:o:)foo} +  foo='\u65\0123^X\C-x' +  print -r ${(g::)foo} +  foo='^X' +  bar='\C-\130' +  [[ ${(g:c:)foo} == ${(g:oe:)bar} ]] +  echo $? +0:${(g)...} +>eS +>eS^X\C-x +>0 + +  foo='I'\''m nearly out of my mind with tedium' +  bar=foo +  print ${(P)bar} +0:${(P)...} +>I'm nearly out of my mind with tedium +#' deconfuse emacs + +  foo=(I could be watching that programme I recorded) +  print ${(o)foo} +  print ${(oi)foo} +  print ${(O)foo} +  print ${(Oi)foo} +0:${(o)...}, ${(O)...} +>I I be could programme recorded that watching +>be could I I programme recorded that watching +>watching that recorded programme could be I I +>watching that recorded programme I I could be + +  foo=(yOU KNOW, THE ONE WITH wILLIAM dALRYMPLE) +  bar=(doing that tour of India.) +  print ${(L)foo} +  print ${(U)bar} +0:${(L)...}, ${(U)...} +>you know, the one with william dalrymple +>DOING THAT TOUR OF INDIA. + +  foo='instead here I am stuck by the computer' +  print ${(C)foo} +0:${(C)...} +>Instead Here I Am Stuck By The Computer + +  foo=$'\x7f\x00' +  print -r -- ${(V)foo} +0:${(V)...} +>^?^@ + +  foo='playing '\''stupid'\'' "games" \w\i\t\h $quoting.' +  print -r ${(q)foo} +  print -r ${(qq)foo} +  print -r ${(qqq)foo} +  print -r ${(qqqq)foo} +  print -r ${(q-)foo} +0:${(q...)...} +>playing\ \'stupid\'\ \"games\"\ \\w\\i\\t\\h\ \$quoting. +>'playing '\''stupid'\'' "games" \w\i\t\h $quoting.' +>"playing 'stupid' \"games\" \\w\\i\\t\\h \$quoting." +>$'playing \'stupid\' "games" \\w\\i\\t\\h $quoting.' +>'playing '\'stupid\'' "games" \w\i\t\h $quoting.' + +  print -r ${(qqqq):-""} +0:workers/36551: literal empty string in ${(qqqq)...} +>$'' + +  x=( a '' '\b' 'c d' '$e' ) +  print -r ${(q)x} +  print -r ${(q-)x} +0:Another ${(q...)...} test +>a '' \\b c\ d \$e +>a '' '\b' 'c d' '$e' + +  print -r -- ${(q-):-foo} +  print -r -- ${(q-):-foo bar} +  print -r -- ${(q-):-"*(.)"} +  print -r -- ${(q-):-"wow 'this is cool' or is it?"} +  print -r -- ${(q-):-"no-it's-not"} +0:${(q-)...} minimal single quoting +>foo +>'foo bar' +>'*(.)' +>'wow '\''this is cool'\'' or is it?' +>no-it\'s-not + +  foo="'and now' \"even the pubs\" \\a\\r\\e shut." +  print -r ${(Q)foo} +0:${(Q)...} +>and now even the pubs are shut. + +  foo="X$'\x41'$'\x42'Y" +  print -r ${(Q)foo} +0:${(Q)...} with handling of $'...' +>XABY + +  # The following may look a bit random. +  # For the split we are checking that anything that +  # would normally be followed by a different word has +  # an argument break after it and anything that wouldn't doesn't. +  # For the (Q) we are simply checking that nothing disappears +  # in the parsing. +  foo='<five> {six} (seven) >eight< }nine{ |forty-two| $many$ )ten( more' +  array=(${(z)foo}) +  print -l ${(Q)array} +0:${(z)...} and ${(Q)...} for some hard to parse cases +>< +>five +>> +>{six} +>( +>seven +>) +>> +>eight +>< +>}nine{ +>| +>forty-two +>| +>$many$ +>) +>ten( more + +  strings=( +    'foo=(1 2 3)' +    '(( 3 + 1 == 8 / 2 ))' +    'for (( i = 1 ; i < 10 ; i++ ))' +    '((0.25542 * 60) - 15)*60' +    'repeat 3 (x)' +    'repeat 3 (echo foo; echo bar)' +    'repeat $(( 2 + 4 )) (x)' +    'repeat $( : foo bar; echo 4) (x)' +    'repeat "1"'\''2'\''$(( 3 + 0 ))$((echo 4);)\ 5 (x)' +  ) +  for string in $strings; do +    array=(${(z)string}) +    for (( i = 1; i <= ${#array}; i++ )); do +      print -r -- "${i}:${array[i]}:" +    done +  done +0:Some syntactical expressions that are hard to split into words with (z). +>1:foo=(: +>2:1: +>3:2: +>4:3: +>5:): +>1:(( 3 + 1 == 8 / 2 )): +>1:for: +>2:((: +# Leading whitespace is removed, because the word proper hasn't started; +# trailing whitespace is left because the word is terminated by the +# semicolon or double parentheses.  Bit confusing but sort of consistent. +>3:i = 1 ;: +>4:i < 10 ;: +>5:i++ : +>6:)): +# This one needs resolving between a math expression and +# a command, which causes interesting effects internally. +>1:(: +>2:(: +>3:0.25542: +>4:*: +>5:60: +>6:): +>7:-: +>8:15: +>9:): +>10:*60: +>1:repeat: +>2:3: +>3:(: +>4:x: +>5:): +>1:repeat: +>2:3: +>3:(: +>4:echo: +>5:foo: +>6:;: +>7:echo: +>8:bar: +>9:): +>1:repeat: +>2:$(( 2 + 4 )): +>3:(: +>4:x: +>5:): +>1:repeat: +>2:$( : foo bar; echo 4): +>3:(: +>4:x: +>5:): +>1:repeat: +>2:"1"'2'$(( 3 + 0 ))$((echo 4);)\ 5: +>3:(: +>4:x: +>5:): + + +  line=$'A line with # someone\'s comment\nanother line # (1 more\nanother one' +  print "*** Normal ***" +  print -l ${(z)line} +  print "*** Kept ***" +  print -l ${(Z+c+)line} +  print "*** Removed ***" +  print -l ${(Z+C+)line} +0:Comments with (z) +>*** Normal *** +>A +>line +>with +># +>someone's comment +>another line # (1 more +>another one +>*** Kept *** +>A +>line +>with +># someone's comment +>; +>another +>line +># (1 more +>; +>another +>one +>*** Removed *** +>A +>line +>with +>; +>another +>line +>; +>another +>one + +  line='with comment # at the end' +  print -l ${(Z+C+)line} +0:Test we don't get an additional newline token +>with +>comment + +  line=$'echo one\necho two # with a comment\necho three' +  print -l ${(Z+nc+)line} +0:Treating zplit newlines as ordinary whitespace +>echo +>one +>echo +>two +># with a comment +>echo +>three + +  print -rl - ${(z):-":;(( echo 42 "} +0:${(z)} with incomplete math expressions +>: +>; +>(( echo 42  + +  # From parse error on it's not possible to split. +  # Just check we get the complete string. +  foo='echo $(|||) bar' +  print -rl ${(z)foo} +0:$($(z)} with parse error in command substitution. +>echo +>$(|||) bar + +  psvar=(dog) +  setopt promptsubst +  foo='It shouldn'\''t $(happen) to a %1v.' +  bar='But `echo what can you do\?`' +  print -r ${(%)foo} +  print -r ${(%%)bar} +0:${(%)...} +>It shouldn't $(happen) to a dog. +>But what can you do? + +  foo='unmatched "' +  print ${(QX)foo} +1:${(QX)...} +?(eval):2: unmatched " +# " deconfuse emacs + +  array=(characters in an array) +  print ${(c)#array} +0:${(c)#...} +>22 + +  print ${(w)#array} +  str='colon::bolon::solon' +  print ${(ws.:.)#str} +  print ${(Ws.:.)#str} +0:${(w)...}, ${(W)...} +>4 +>3 +>5 + +  typeset -A assoc +  assoc=(key1 val1 key2 val2) +  print ${(o)assoc} +  print ${(ok)assoc} +  print ${(ov)assoc} +  print ${(okv)assoc} +0:${(k)...}, ${(v)...} +>val1 val2 +>key1 key2 +>val1 val2 +>key1 key2 val1 val2 + +  word="obfuscatory" +  print !${(l.16.)word}! +${(r.16.)word}+ +0:simple padding +>!     obfuscatory! +obfuscatory     + + +  foo=(resulting words uproariously padded) +  print ${(pl.10..\x22..X.)foo} +0:${(pl...)...} +>Xresulting """"Xwords roariously """Xpadded +#" deconfuse emacs + +  print ${(l.5..X.r.5..Y.)foo} +  print ${(l.6..X.r.4..Y.)foo} +  print ${(l.7..X.r.3..Y.)foo} +  print ${(l.6..X..A.r.6..Y..B.)foo} +  print ${(l.6..X..AROOGA.r.6..Y..BARSOOM.)foo} +0:simultaneous left and right padding +>Xresulting XXXwordsYY proariousl XXpaddedYY +>XXresultin XXXXwordsY uproarious XXXpaddedY +>XXXresulti XXXXXwords Xuproariou XXXXpadded +>XAresultingB XXXAwordsBYY uproariously XXApaddedBYY +>GAresultingB OOGAwordsBAR uproariously OGApaddedBAR + +  foo=(why in goodness name am I doing this) +  print ${(r.5..!..?.)foo} +0:${(r...)...} +>why?! in?!! goodn name? am?!! I?!!! doing this? + +  array=(I\'m simply putting a brave face on) +  print ${(j:--:)array} +0:${(j)...} +>I'm--simply--putting--a--brave--face--on + +  print ${(F)array} +0:${(F)...} +>I'm +>simply +>putting +>a +>brave +>face +>on + +  string='zometimez zis getz zplit on a z' +  print -l ${(s?z?)string} +0:${(s...)...} +>ometime +>  +>is get +>  +>plit on a  + +  str=s +  arr=(a) +  typeset -A ass +  ass=(a a) +  integer i +  float f +  print ${(t)str} ${(t)arr} ${(t)ass} ${(t)i} ${(t)f} +0:${(t)...} +>scalar array association-local integer-local float-local + +  # it's not quite clear that these are actually right unless you know +  # the algorithm:  search along the string for the point at which the +  # first (last) match occurs, for ## (%%), then take the shortest possible +  # version of that for # (%).  it's as good a definition as anything. +  string='where is the white windmill, whispered walter wisely' +  print ${(S)string#h*e} +  print ${(S)string##h*e} +  print ${(S)string%h*e} +  print ${(S)string%%h*e} +0:${(S)...#...} etc. +>wre is the white windmill, whispered walter wisely +>wly +>where is the white windmill, wred walter wisely +>where is the white windmill, wly + +  setopt extendedglob +  print ${(SI:1:)string##w[^[:space:]]# } +  print ${(SI:1+1:)string##w[^[:space:]]# } +  print ${(SI:1+1+1:)string##w[^[:space:]]# } +  print ${(SI:1+1+1+1:)string##w[^[:space:]]# } +0:${(I:...:)...} +>is the white windmill, whispered walter wisely +>where is the windmill, whispered walter wisely +>where is the white whispered walter wisely +>where is the white windmill, walter wisely + +  print ${(MSI:1:)string##w[^[:space:]]# } +0:${(M...)...} +>where  + +  print ${(R)string//w[a-z]# #} +0:${(R)...} +>is the ,  + +  # This (1) doesn't work with // or / +  #      (2) perhaps ought to be 18, to be consistent with normal zsh +  #          substring indexing and with backreferences. +  print ${(BES)string##white} +0:${(BE...)...} +>14 19 + +  print ${(NS)string##white} +0:${(N)...} +>5 + +  string='abcdefghijklmnopqrstuvwxyz' +  print ${${string%[aeiou]*}/(#m)?(#e)/${(U)MATCH}} +0:Rule 1:  Nested substitutions +>abcdefghijklmnopqrsT + +  array=(et Swann avec cette muflerie intermittente) +  string="qui reparaissait chez lui" +  print ${array[4,5]} +  print ${array[4,5][1]} +  print ${array[4,5][1][2,3]} +  print ${string[4,5]} +  print ${string[4,5][1]} +0:Rule 2: Parameter subscripting +>cette muflerie +>cette +>et +> r +>  + +  foo=stringalongamax +  print ${${(P)foo[1,6]}[1,3]} +0:Rule 3: Parameter Name Replacement +>qui + +  print "${array[5,6]}" +  print "${(j.:.)array[1,2]}" +0:Rule 4: Double-Quoted Joining +>muflerie intermittente +>et:Swann + +  print "${${array}[5,7]}" +  print "${${(@)array}[1,2]}" +0:Rule 5: Nested Subscripting +>wan +>et Swann + +  print "${${(@)array}[1,2]#?}" +  print "${(@)${(@)array}[1,2]#?}" +0:Rule 6: Modifiers +>t Swann +>t wann + +  array=(she sells z shells by the z shore) +  (IFS='+'; print ${(s.s.)array}) +0:Rule 7: Forced Joining, and 8: Forced splitting +>he+ ell +z+ hell +by+the+z+ hore + +  setopt shwordsplit +  string='another poxy boring string' +  print -l ${${string}/o/ } +  unsetopt shwordsplit +0:Rule 9: Shell Word Splitting +>an +>ther +>p +>xy +>b +>ring +>string + +  setopt nonomatch +  foo='b* e*' +  print ${(e)~foo} +  print ${(e)~=foo} +  setopt nomatch +0:Rule 10: Re-Evaluation +>b* e* +>boringfile evenmoreboringfile + +  # ${bar} -> $bar  here would yield "bad substitution". +  bar=confinement +  print ${(el.20..X.)${bar}} +0:Rule 11: Padding +>XXXXXXXXXconfinement + +  foo=(bar baz) +  bar=(ax1 bx1) +  print "${(@)${foo}[1]}" +  print "${${(@)foo}[1]}" +  print -l ${(s/x/)bar} +  print -l ${(j/x/s/x/)bar} +  print -l ${(s/x/)bar%%1*} +0:Examples in manual on parameter expansion +>b +>bar +>a +>1 b +>1 +>a +>1 +>b +>1 +>a +> b + +  set If "this test fails" "we have broken" the shell again +  print -l ${1+"$@"} +0:Regression test of ${1+"$@"} bug +>If +>this test fails +>we have broken +>the +>shell +>again + +  set If "this test fails" "we have broken" the shell again +  print -l "${(A)foo::=$@}" +  print -l ${(t)foo} +  print -l $foo +0:Regression test of "${(A)foo=$@}" bug +>If this test fails we have broken the shell again +>array +>If +>this test fails +>we have broken +>the +>shell +>again + +  local sure_that='sure that' varieties_of='varieties of' one=1 two=2 +  extra=(5 4 3) +  unset foo +  set Make $sure_that "this test keeps" on 'preserving all' "$varieties_of" quoted whitespace +  print -l ${=1+"$@"} +  print -l ${(A)=foo=Make $sure_that "this test keeps" on 'preserving all' "$varieties_of" quoted whitespace} +  print ${(t)foo} +  print -l ${=1+$one $two} +  print -l ${1+$extra$two$one} +0:Regression test of ${=1+"$@"} bug and some related expansions +>Make +>sure that +>this test keeps +>on +>preserving all +>varieties of +>quoted +>whitespace +>Make +>sure +>that +>this test keeps +>on +>preserving all +>varieties of +>quoted +>whitespace +>array +>1 +>2 +>5 +>4 +>321 + +  splitfn() { +    emulate -L sh +    local HOME="/differs from/bash" foo='1 2' bar='3 4' +    print -l ${1:-~} +    touch has\ space +    print -l ${1:-*[ ]*} +    print -l ${1:-*[\ ]*} +    print -l ${1:-*} +    print -l ${1:-"$foo" $bar} +    print -l ${==1:-$foo $bar} +    rm has\ space +  } +  splitfn +0:More bourne-shell-compatible nested word-splitting with wildcards and ~ +>/differs from/bash +>*[ +>]* +>has space +>boringfile +>evenmoreboringfile +>has space +>1 2 +>3 +>4 +>1 2 3 4 + +  splitfn() { +    local IFS=.- +    local foo=1-2.3-4 +    # +    print "Called with argument '$1'" +    print "No quotes" +    print -l ${=1:-1-2.3-4} ${=1:-$foo} +    print "With quotes on default argument only" +    print -l ${=1:-"1-2.3-4"} ${=1:-"$foo"} +  } +  print 'Using "="' +  splitfn +  splitfn 5.6-7.8 +  # +  splitfn() { +    emulate -L zsh +    setopt shwordsplit +    local IFS=.- +    local foo=1-2.3-4 +    # +    print "Called with argument '$1'" +    print "No quotes" +    print -l ${1:-1-2.3-4} ${1:-$foo} +    print "With quotes on default argument only" +    print -l ${1:-"1-2.3-4"} ${1:-"$foo"} +  } +  print Using shwordsplit +  splitfn +  splitfn 5.6-7.8 +0:Test of nested word splitting with and without quotes +>Using "=" +>Called with argument '' +>No quotes +>1 +>2 +>3 +>4 +>1 +>2 +>3 +>4 +>With quotes on default argument only +>1-2.3-4 +>1-2.3-4 +>Called with argument '5.6-7.8' +>No quotes +>5 +>6 +>7 +>8 +>5 +>6 +>7 +>8 +>With quotes on default argument only +>5 +>6 +>7 +>8 +>5 +>6 +>7 +>8 +>Using shwordsplit +>Called with argument '' +>No quotes +>1 +>2 +>3 +>4 +>1 +>2 +>3 +>4 +>With quotes on default argument only +>1-2.3-4 +>1-2.3-4 +>Called with argument '5.6-7.8' +>No quotes +>5 +>6 +>7 +>8 +>5 +>6 +>7 +>8 +>With quotes on default argument only +>5 +>6 +>7 +>8 +>5 +>6 +>7 +>8 + +# Tests a long-standing bug with joining on metafied characters in IFS +  (array=(one two three) +  IFS=$'\0' +  foo="$array" +  for (( i = 1; i <= ${#foo}; i++ )); do +    char=${foo[i]} +    print $(( #char )) +  done) +0:Joining with NULL character from IFS +>111 +>110 +>101 +>0 +>116 +>119 +>111 +>0 +>116 +>104 +>114 +>101 +>101 + +  unset SHLVL +  (( SHLVL++ )) +  print $SHLVL +0:Unsetting and recreation of numerical special parameters +>1 + +  unset manpath +  print $+MANPATH +  manpath=(/here /there) +  print $MANPATH +  unset MANPATH +  print $+manpath +  MANPATH=/elsewhere:/somewhere +  print $manpath +0:Unsetting and recreation of tied special parameters +>0 +>/here:/there +>0 +>/elsewhere /somewhere + +  local STRING=a:b +  typeset -T STRING string +  print $STRING $string +  unset STRING +  set -A string x y z +  print $STRING $string +  STRING=a:b +  typeset -T STRING string +  print $STRING $string +  unset STRING +  set -A string x y z +  print $STRING $string +  STRING=a:b +  typeset -T STRING string +  print $STRING $string +  unset string +  STRING=x:y:z +  print $STRING $string +  STRING=a:b +  typeset -T STRING string +  print $STRING $string +  unset string +  STRING=x:y:z +  print $STRING $string +0:Unsetting and recreation of tied normal parameters +>a:b a b +>x y z +>a:b a b +>x y z +>a:b a b +>x:y:z +>a:b a b +>x:y:z + +  typeset -T tied1 tied2 + +  typeset -T tied2 tied1 + +1:Attempts to swap tied variables are safe but futile +?(eval):typeset:2: already tied as non-scalar: tied2 + +  string='look for a match in here' +  if [[ ${string%%(#b)(match)*} = "look for a " ]]; then +    print $match[1] $mbegin[1] $mend[1] $string[$mbegin[1],$mend[1]] +    print $#match $#mbegin $#mend +  else +    print That didn\'t work. +  fi +0:Parameters associated with backreferences +>match 12 16 match +>1 1 1 +#' deconfuse emacs + +  string='and look for a MATCH in here' +  if [[ ${(S)string%%(#m)M*H} = "and look for a  in here" ]]; then +    print $MATCH $MBEGIN $MEND $string[$MBEGIN,$MEND] +    print $#MATCH +  else +    print Oh, dear.  Back to the drawing board. +  fi +0:Parameters associated with (#m) flag +>MATCH 16 20 MATCH +>5 + +  string='this is a string' +  print ${string//(#m)s/$MATCH $MBEGIN $MEND} +0:(#m) flag with pure string +>this 4 4 is 7 7 a s 11 11tring + +  print ${${~:-*}//(#m)*/$MATCH=$MATCH} +0:(#m) flag with tokenized input +>*=* + +  print -l JAMES${(u)${=:-$(echo yes yes)}}JOYCE +  print -l JAMES${(u)${=:-$(echo yes yes she said yes i will yes)}}JOYCE +0:Bug with (u) flag reducing arrays to one element +>JAMESyesJOYCE +>JAMESyes +>she +>said +>i +>willJOYCE + +  print -l JAMES${(u)${=:-$(echo yes yes she said yes i will yes she said she will and yes she did yes)}}JOYCE +0:New hash seive unique algorithm for arrays of more than 10 elements +>JAMESyes +>she +>said +>i +>will +>and +>didJOYCE + +  foo= +  print "${${foo}/?*/replacement}" +0:Quoted zero-length strings are handled properly +> + +  file=aleftkept +  print ${file//(#b)(*)left/${match/a/andsome}} +  print ${file//(#b)(*)left/${match//a/andsome}} +0:Substitutions where $match is itself substituted in the replacement +>andsomekept +>andsomekept + +  file=/one/two/three/four +  print ${file:fh} +  print ${file:F.1.h} +  print ${file:F+2+h} +  print ${file:F(3)h} +  print ${file:F<4>h} +  print ${file:F{5}h} +0:Modifiers with repetition +>/ +>/one/two/three +>/one/two +>/one +>/ +>/ + +  baz=foo/bar +  zab=oof+rab +  print ${baz:s/\//+/} +  print "${baz:s/\//+/}" +  print ${zab:s/+/\//} +  print "${zab:s/+/\//}" +0:Quoting of separator in substitution modifier +>foo+bar +>foo+bar +>oof/rab +>oof/rab + +  bsbs='X\\\\Y' +  print -r -- ${bsbs:s/\\/\\/} +  print -r -- "${bsbs:s/\\/\\/}" +  print -r -- ${bsbs:s/\\\\/\\\\/} +  print -r -- "${bsbs:s/\\\\/\\\\/}" +  print -r -- ${bsbs:gs/\\/\\/} +  print -r -- "${bsbs:gs/\\/\\/}" +  print -r -- ${bsbs:gs/\\\\/\\\\/} +  print -r -- "${bsbs:gs/\\\\/\\\\/}" +0:Handling of backslashed backslashes in substitution modifier +>X\\\\Y +>X\\\\Y +>X\\\\Y +>X\\\\Y +>X\\\\Y +>X\\\\Y +>X\\\\Y +>X\\\\Y + +  print -r ${${:-one/two}:s,/,X&Y,} +  print -r ${${:-one/two}:s,/,X\&Y,} +  print -r ${${:-one/two}:s,/,X\\&Y,} +  print -r "${${:-one/two}:s,/,X&Y,}" +  print -r "${${:-one/two}:s,/,X\&Y,}" +  print -r "${${:-one/two}:s,/,X\\&Y,}" +0:Quoting of ampersand in substitution modifier RHS +>oneX/Ytwo +>oneX&Ytwo +>oneX\/Ytwo +>oneX/Ytwo +>oneX&Ytwo +>oneX\/Ytwo + +  nully=($'a\0c' $'a\0b\0b' $'a\0b\0a' $'a\0b\0' $'a\0b' $'a\0' $'a') +  for string in ${(o)nully}; do +    for (( i = 1; i <= ${#string}; i++ )); do +      foo=$string[i] +      printf "%02x" $(( #foo )) +    done +    print +  done +0:Sorting arrays with embedded nulls +>61 +>6100 +>610062 +>61006200 +>6100620061 +>6100620062 +>610063 + +  array=(X) +  patterns=("*X*" "spong" "a[b") +  for pat in $patterns; do +    print A${array[(r)$pat]}B C${array[(I)$pat]}D +  done +0:Bad patterns should never match array elements +>AXB C1D +>AB C0D +>AB C0D + +  foo=(a6 a117 a17 b6 b117 b17) +  print ${(n)foo} +  print ${(On)foo} +0:Numeric sorting +>a6 a17 a117 b6 b17 b117 +>b117 b17 b6 a117 a17 a6 + +  x=sprodj +  x[-10]=scrumf +  print $x +0:Out of range negative scalar subscripts +>scrumfsprodj + +  a=(some sunny day) +  a[-10]=(we\'ll meet again) +  print -l $a +0:Out of range negative array subscripts +>we'll +>meet +>again +>some +>sunny +>day + +# ' emacs likes this close quote + +  a=(sping spang spong bumble) +  print ${a[(i)spong]} +  print ${a[(i)spung]} +  print ${a[(ib.1.)spong]} +  print ${a[(ib.4.)spong]} +  print ${a[(ib.10.)spong]} +0:In and out of range reverse matched indices without and with b: arrays +>3 +>5 +>3 +>5 +>5 + +  a="thrimblewuddlefrong" +  print ${a[(i)w]} +  print ${a[(i)x]} +  print ${a[(ib.3.)w]} +  print ${a[(ib.10.)w]} +  print ${a[(ib.30.)w]} +0:In and out of range reverse matched indices without and with b: strings +>9 +>20 +>9 +>20 +>20 + +  foo="line:with::missing::fields:in:it" +  print -l ${(s.:.)foo} +0:Removal of empty fields in unquoted splitting +>line +>with +>missing +>fields +>in +>it + +  foo="line:with::missing::fields:in:it" +  print -l "${(s.:.)foo}" +0:Hacky removal of empty fields in quoted splitting with no "@" +>line +>with +>missing +>fields +>in +>it + +  foo="line:with::missing::fields:in:it:" +  print -l "${(@s.:.)foo}" +0:Retention of empty fields in quoted splitting with "@" +>line +>with +> +>missing +> +>fields +>in +>it +> + +  str=abcd +  print -l ${(s..)str} +  print -l "${(s..)str}" +0:splitting of strings into characters +>a +>b +>c +>d +>a +>b +>c +>d + +  array=('%' '$' 'j' '*' '$foo') +  print ${array[(i)*]} "${array[(i)*]}" +  print ${array[(ie)*]} "${array[(ie)*]}" +  key='$foo' +  print ${array[(ie)$key]} "${array[(ie)$key]}" +  key='*' +  print ${array[(ie)$key]} "${array[(ie)$key]}" +0:Matching array indices with and without quoting +>1 1 +>4 4 +>5 5 +>4 4 + +# Ordering of associative arrays is arbitrary, so we need to use +# patterns that only match one element. +  typeset -A assoc_r +  assoc_r=(star '*' of '*this*' and '!that!' or '(the|other)') +  print ${(kv)assoc_r[(re)*]} +  print ${(kv)assoc_r[(re)*this*]} +  print ${(kv)assoc_r[(re)!that!]} +  print ${(kv)assoc_r[(re)(the|other)]} +  print ${(kv)assoc_r[(r)*at*]} +  print ${(kv)assoc_r[(r)*(ywis|bliss|kiss|miss|this)*]} +  print ${(kv)assoc_r[(r)(this|that|\(the\|other\))]} +0:Reverse subscripting associative arrays with literal matching +>star * +>of *this* +>and !that! +>or (the|other) +>and !that! +>of *this* +>or (the|other) + +  print $ZSH_SUBSHELL +  (print $ZSH_SUBSHELL) +  ( (print $ZSH_SUBSHELL) ) +  ( (print $ZSH_SUBSHELL); print $ZSH_SUBSHELL ) +  print $(print $ZSH_SUBSHELL) +  cat =(print $ZSH_SUBSHELL) +0:ZSH_SUBSHELL +>0 +>1 +>2 +>2 +>1 +>1 +>1 + +  foo=("|" "?") +  [[ "|" = ${(j.|.)foo} ]] && print yes || print no +  [[ "|" = ${(j.|.)~foo} ]] && print yes || print no +  [[ "|" = ${(~j.|.)foo} ]] && print yes || print no +  [[ "|" = ${(~~j.|.)foo} ]] && print yes || print no +  [[ "|" = ${(j.|.~)foo} ]] && print yes || print no +  [[ "x" = ${(j.|.)foo} ]] && print yes || print no +  [[ "x" = ${(j.|.)~foo} ]] && print yes || print no +  [[ "x" = ${(~j.|.)foo} ]] && print yes || print no +  [[ "x" = ${(~~j.|.)foo} ]] && print yes || print no +  [[ "x" = ${(j.|.~)foo} ]] && print yes || print no +0:GLOBSUBST only on parameter substitution arguments +>no +>yes +>yes +>no +>no +>no +>yes +>no +>no +>no + +  rcexbug() { +    emulate -L zsh +    setopt rcexpandparam +    local -A hash +    local -a full empty +    full=(X x) +    hash=(X x) +    print ORDINARY ARRAYS +    : The following behaves as documented in zshoptions +    print FULL expand=$full +    : Empty arrays remove the adjacent argument +    print EMPTY expand=$empty +    print ASSOCIATIVE ARRAY +    print Subscript flags returning many values +    print FOUND key=$hash[(I)X] val=$hash[(R)x] +    : This should behave like $empty, and does +    print LOST key=$hash[(I)y] val=$hash[(R)Y] +    print Subscript flags returning single values +    : Doc says "substitutes ... empty string" +    : so must not behave like an empty array +    print STRING key=$hash[(i)y] val=$hash[(r)Y] +  } +  rcexbug +0:Lookup failures on elements of arrays with RC_EXPAND_PARAM +>ORDINARY ARRAYS +>FULL expand=X expand=x +>EMPTY +>ASSOCIATIVE ARRAY +>Subscript flags returning many values +>FOUND key=X val=x +>LOST +>Subscript flags returning single values +>STRING key= val= + +   print $zsh_eval_context[1] +   [[ $ZSH_EVAL_CONTEXT = ${(j.:.)zsh_eval_context} ]] || print Not equal! +   (( icontext = ${#zsh_eval_context} + 1 )) +   contextfn() { print $(print $zsh_eval_context[icontext,-1]); } +   contextfn +0:$ZSH_EVAL_CONTEXT and $zsh_eval_context +>toplevel +>shfunc cmdsubst + +   foo="123456789" +   print ${foo:3} +   print ${foo: 1 + 3} +   print ${foo:$(( 2 + 3))} +   print ${foo:$(echo 3 + 3)} +   print ${foo:3:1} +   print ${foo: 1 + 3:(4-2)/2} +   print ${foo:$(( 2 + 3)):$(( 7 - 6 ))} +   print ${foo:$(echo 3 + 3):`echo 4 - 3`} +   print ${foo: -1} +   print ${foo: -10} +   print ${foo:5:-2} +0:Bash-style offsets, scalar +>456789 +>56789 +>6789 +>789 +>4 +>5 +>6 +>7 +>9 +>123456789 +>67 + +   foo=(1 2 3 4 5 6 7 8 9) +   print ${foo:3} +   print ${foo: 1 + 3} +   print ${foo:$(( 2 + 3))} +   print ${foo:$(echo 3 + 3)} +   print ${foo:3:1} +   print ${foo: 1 + 3:(4-2)/2} +   print ${foo:$(( 2 + 3)):$(( 7 - 6 ))} +   print ${foo:$(echo 3 + 3):`echo 4 - 3`} +   print ${foo: -1} +   print ${foo: -10} +   print ${foo:5:-2} +0:Bash-style offsets, array +>4 5 6 7 8 9 +>5 6 7 8 9 +>6 7 8 9 +>7 8 9 +>4 +>5 +>6 +>7 +>9 +>1 2 3 4 5 6 7 8 9 +>6 7 + +   testfn() { +     emulate -L sh +     set -A foo 1 2 3 +     set -- 1 2 3 +     str=abc +     echo ${foo[*]:0:1} +     echo ${foo[*]:1:1} +     echo ${foo[*]: -1:1} +     : +     echo ${*:0:1} +     echo ${*:1:1} +     echo ${*: -1:1} +     : +     echo ${str:0:1} +     echo ${str:1:1} +     echo ${str: -1:1} +   } +   testfn +0:Bash-style offsets, Bourne-style indexing +>1 +>2 +>3 +>testfn +>1 +>3 +>a +>b +>c + +   printf "%n" '[0]' +1:Regression test for identifier test +?(eval):1: not an identifier: [0] + +   str=rts +   print ${str:0:} +1:Regression test for missing length after offset +?(eval):2: unrecognized modifier + +   foo="123456789" +   print ${foo:5:-6} +1:Regression test for total length < 0 in string +?(eval):2: substring expression: 3 < 5 + +   foo=(1 2 3 4 5 6 7 8 9) +   print ${foo:5:-6} +1:Regression test for total length < 0 in array +?(eval):2: substring expression: 3 < 5 + +   foo=(${(0)"$(print -n)"}) +   print ${#foo} +0:Nularg removed from split empty string +>0 + +   (set -- a b c +    setopt shwordsplit +    IFS= +    print -rl "$*" +    unset IFS +    print -rl "$*") +0:Regression test for shwordsplit with null or unset IFS and quoted array +>abc +>a b c + +   foo= +   print ${foo:wq} +   print ${:wq} +0:Empty parameter should not cause modifiers to crash the shell +> +> + +# This used to cause uncontrolled behaviour, but at best +# you got the wrong output so the check is worth it. +   args() { print $#; } +   args ${:*} +   args ${:|} +0:Intersection and disjunction with empty parameters +>0 +>0 + +  foo=(a b c) +  bar=(1 2 3) +  print ${foo:^bar} +  print ${foo:^^bar} +  foo=(a b c d) +  bar=(1 2) +  print ${foo:^bar} +  print ${foo:^^bar} +  foo=('a a' b) +  bar=(1 '2 2') +  print -l "${foo:^bar}" +  print -l "${(@)foo:^bar}" +0:Zipping arrays, correct output +>a 1 b 2 c 3 +>a 1 b 2 c 3 +>a 1 b 2 +>a 1 b 2 c 1 d 2 +# maybe this should be changed to output "a a b 1" +>a a b +>1 +>a a +>1 +>b +>2 2 + +  foo=(a b c) +  bar=() +  print ${foo:^bar} +  print ${foo:^^bar} +  print ${bar:^foo} +  print ${bar:^^foo} +  print ${bar:^bar} +  print ${bar:^^bar} +0:Zipping arrays, one or both inputs empty +> +>a b c +> +>a b c +> +> + +  foo=text +  bar=() +  print ${foo:^bar} +  print ${bar:^^foo} +  bar=other +  print ${foo:^bar} +  bar=(array elements) +  print ${foo:^bar} +  print ${foo:^^bar} +  print ${bar:^foo} +  print ${bar:^^foo} +0:Zipping arrays, scalar input +> +>text +>text other +>text array +>text array text elements +>array text +>array text elements text + +  foo=(a b c) +  print ${foo:^^^bar} +1:Zipping arrays, parsing +?(eval):2: not an identifier: ^bar + +  (setopt nounset +  print ${foo:^noexist}) +1:Zipping arrays, NO_UNSET part 1 +?(eval):2: noexist: parameter not set + +  (setopt nounset +  print ${noexist:^foo}) +1:Zipping arrays, NO_UNSET part 2 +?(eval):2: noexist: parameter not set + +  expr="a@b,c@d:e@f,g@h:i@j,k@l" +  for sep in : , @; do +    print -l ${(ps.$sep.)expr} +  done +0:Use of variable to get separator when splitting parameter +>a@b,c@d +>e@f,g@h +>i@j,k@l +>a@b +>c@d:e@f +>g@h:i@j +>k@l +>a +>b,c +>d:e +>f,g +>h:i +>j,k +>l + +  SHLVL=1 +  $ZTST_testdir/../Src/zsh -fc 'echo $SHLVL' +  $ZTST_testdir/../Src/zsh -fc '(echo $SHLVL)' +0:SHLVL appears sensible when about to exit shell +>2 +>2 + +  # SHLVL is incremented twice and decremented once in between. +  SHLVL=1 +  $ZTST_testdir/../Src/zsh -fc $ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"' +  $ZTST_testdir/../Src/zsh -fc '('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL")' +  $ZTST_testdir/../Src/zsh -fc '( ('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"))' +0:SHLVL decremented upon implicit exec optimisation +>2 +>2 +>2 + +  # SHLVL is incremented twice with no decrement in between. +  SHLVL=1 +  $ZTST_testdir/../Src/zsh -fc '('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"); exit' +  $ZTST_testdir/../Src/zsh -fc '(exec '$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"); exit' +  $ZTST_testdir/../Src/zsh -fc '( ('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"); exit)' +0:SHLVL not decremented upon exec in subshells +>3 +>3 +>3 + +# The following tests the return behaviour of parsestr/parsestrnoerr +  alias param-test-alias='print $'\''\x45xpanded in substitution'\'  +  param='$(param-test-alias)' +  print ${(e)param} +0:Alias expansion in command substitution in parameter evaluation +>Expanded in substitution + +  a=1 b=2 c=3 +  : One; +  function { +      : Two +      echo $_ +      print -l $argv +  } $_ Three +  print -l $_ Four; +0:$_ with anonymous function +>Two +>One +>Three +>Three +>Four + +  a=1 b=2 c=3 +  : One +  function { +      : Two +      echo $_ +      print -l $argv +  } +  print -l "$_" Four +0:$_ with anonymous function without arguments +>Two +> +> +>Four + +  funnychars='The qu*nk br!wan f@x j/mps o[]r \(e la~# ^"&;' +  [[ $funnychars = ${~${(b)funnychars}} ]] +0:${(b)...} quoting protects from GLOB_SUBST + +  set -- foo +  echo $(( $#*3 )) +  emulate sh -c 'nolenwithoutbrace() { echo $#-1; }' +  nolenwithoutbrace +0:Avoid confusion after overloaded characters in braceless substitution in sh +>13 +>0-1 + +  a="aaa bab cac" +  b=d +  echo $a:gs/a/${b}/ +  a=(aaa bab cac) +  echo $a:gs/a/${b}/ +0:History modifier works the same for scalar and array substitution +>ddd bdb cdc +>ddd bdb cdc + + a=1_2_3_4_5_6 + print ${a#(*_)(#c2)} + print ${a#(*_)(#c5)} + print ${a#(*_)(#c7)} +0:Complicated backtracking with match counts +>3_4_5_6 +>6 +>1_2_3_4_5_6 + + (setopt shwordsplit + do_test() { +   print $#: "$@" + } + foo=bar + foo2="bar bar" + do_test ${:- foo } + do_test ${:- foo bar } + do_test ${:- $foo } + do_test ${:- $foo2 } + do_test x${:- foo }y + do_test x${:- foo bar }y + do_test x${:- $foo }y + do_test x${:- $foo2 }y + do_test x${foo:+ $foo }y + ) +0:We Love SH_WORD_SPLIT Day celebrated with space at start of internal subst +>1: foo +>2: foo bar +>1: bar +>2: bar bar +>3: x foo y +>4: x foo bar y +>3: x bar y +>4: x bar bar y +>3: x bar y + + (unsetopt shwordsplit # default, for clarity + do_test() { +   print $#: "$@" + } + foo=bar + foo2="bar bar" + do_test ${:- foo } + do_test ${:- foo bar } + do_test ${:- $foo } + do_test ${:- $foo2 } + do_test x${:- foo }y + do_test x${:- foo bar }y + do_test x${:- $foo }y + do_test x${:- $foo2 }y + do_test x${foo:+ $foo }y + ) +0:We Love NO_SH_WORD_SPLIT Even More Day celebrated as sanity check +>1:  foo  +>1:  foo bar  +>1:  bar  +>1:  bar bar  +>1: x foo y +>1: x foo bar y +>1: x bar y +>1: x bar bar y +>1: x bar y + +  testfn() { +    local scalar=obfuscation +    local -a array=(alpha bravo charlie delta echo foxtrot) +    local -A assoc=(one eins two zwei three drei four vier) +    local name subscript +    for name subscript in scalar 3 array 5 assoc three; do +      print ${${(P)name}[$subscript]} +    done +  } +  testfn +0:${(P)...} with normal subscripting +>f +>echo +>drei + +  testfn() { +    local s1=foo s2=bar +    local -a val=(s1) +    print ${${(P)val}[1,3]} +    val=(s1 s2) +    print ${${(P)val}[1,3]} +  } +  testfn +1:${(P)...} with array as name +>foo +?testfn:5: parameter name reference used with array + +  testfn() { +    local -A assoc=(one buckle two show three knock four door) +    local name='assoc[two]' +    print ${${(P)name}[2,3]} +  } +  testfn +0:${(P)...} with internal subscripting +>ho + +  testfn() { +    local one=two +    local two=three +    local three=four +    local -a four=(all these worlds belong to foo) +    print ${(P)${(P)${(P)one}}} +    print ${${(P)${(P)${(P)one}}}[3]} +  } +  testfn +0:nested parameter name references +>all these worlds belong to foo +>worlds + +  ( +  path=(/random /value) +  testfn1() { +    local path= +    print $#path +  } +  testfn1 +  testfn2() { +    local path=/somewhere +    print $#path $path +  } +  testfn2 +  print $#path $path +  ) +0:Local special variables with loose typing +>0 +>1 /somewhere +>2 /random /value + +  print -r -- ${(q+):-} +  print -r -- ${(q+)IFS} +  print -r -- ${(q+):-oneword} +  print -r -- ${(q+):-two words} +  print -r -- ${(q+):-three so-called \'words\'} +  (setopt rcquotes; print -r -- ${(q+):-three so-called \'words\'}) +0:${(q+)...} +>'' +>$' \t\n\C-@' +>oneword +>'two words' +>'three so-called '\''words'\' +>'three so-called ''words''' + +  array=(one two three) +  array[1]=${nonexistent:-foo} +  print $array +0:"-" works after "[" in same expression (Dash problem) +>foo two three + +  ( +  setopt shwordsplit +  set -- whim:wham:whom +  IFS=: +  print -l $@ +  ) +0:Splitting of $@ on IFS: single element +>whim +>wham +>whom + +  ( +  setopt shwordsplit +  set -- one:two bucklemy:shoe +  IFS=: +  print -l $@ +  ) +0:Splitting of $@ on IFS: multiple elements +# No forced joining in this case +>one +>two +>bucklemy +>shoe + +  ( +  set -- one:two bucklemy:shoe +  print -l ${(s.:.)@} +  ) +0:Splitting of $@ on (s): multiple elements +# Forced joining in this case +>one +>two bucklemy +>shoe + +  ( +  set -- one:two bucklemy:shoe +  print -l ${(@s.:.)@} +  ) +0:Splitting of $@ on (@s): multiple elements +# Forced non-joining in this case +>one +>two +>bucklemy +>shoe + +  ( +  set -- one:two bucklemy:shoe +  IFS= +  setopt shwordsplit +  print -l ${@} ${(s.:.)*} ${(s.:.j.-.)*} +  ) +0:Joining of $@ does not happen when IFS is empty, but splitting $* does +>one:two +>bucklemy:shoe +>one +>twobucklemy +>shoe +>one +>two-bucklemy +>shoe + +  ( +  set -- "one two" "bucklemy shoe" +  IFS= +  setopt shwordsplit rcexpandparam +  print -l "X${(@j.-.)*}" +  ) +0:Use of @ does not prevent forced join with j +>Xone two-bucklemy shoe + +  () { print -r -- "${(q)1}" "${(b)1}" "${(qq)1}" } '=foo' +0:(q) and (b) quoting deal with the EQUALS option +>\=foo =foo '=foo' + +  args() { print $#; } +  a=(foo) +  args "${a[3,-1]}" +  args "${(@)a[3,-1]}" +0:Out-of-range multiple array subscripts with quoting, with and without (@) +>1 +>0 + +  a='~-/'; echo $~a +0:Regression: "-" became Dash in workers/37689, breaking ~- expansion +*>* +F:We do not care what $OLDPWD is, as long as it doesn't cause an error | 
