1#! test/for/moderni/sh 2# See the file LICENSE in the main modernish directory for the licence. 3 4# Regression tests related to string and text processing. 5 6TEST title="whitespace/non-whitespace IFS delimiters" 7 IFS=': ' 8 v=' :: \on\e :\tw'\''o \th\'\''re\e :\\'\''fo\u\r: : : ' 9 set -- $v 10 IFS= 11 v=${#},${1-U},${2-U},${3-U},${4-U},${5-U},${6-U},${7-U},${8-U},${9-U},${10-U},${11-U},${12-U} 12 case $v in 13 ( '8,,,\on\e,\tw'\''o,\th\'\''re\e,\\'\''fo\u\r,,,U,U,U,U' ) 14 mustNotHave QRK_IFSFINAL ;; 15 ( '9,,,\on\e,\tw'\''o,\th\'\''re\e,\\'\''fo\u\r,,,,U,U,U' ) 16 mustHave QRK_IFSFINAL ;; 17 ( '11,,,\on\e,,\tw'\''o,\th\'\''re\e,,\\'\''fo\u\r,,,,U,' ) 18 # pdksh 19 failmsg="incorrect IFS whitespace removal" 20 return 1 ;; 21 ( '9,,,on\e,tw'\''o,th\'\''re\e,\'\''fo\u\r,,,,U,U,U,' ) 22 # yash 2.8 to 2.37 23 failmsg=="split eats initial backslashes" 24 return 1 ;; 25 ( '9,,,\on\e,\tw'\''o,\th\'\''re\e,\'\''fo\u\r,,,,U,U,U,' ) 26 # zsh up to 4.2.6 27 failmsg="split eats first of double backslash" 28 return 1 ;; 29 ( '8,,\on\e,\tw'\''o,\th\'\''re\e,\\'\''fo\u\r,,,,U,U,U,U,' ) 30 # ksh93 Version M 1993-12-28 p 31 # Bug with IFS whitespace: an initial empty whitespace-separated field 32 # appears at the end of the expansion result instead of the start 33 # if IFS contains both whitespace and non-whitespace characters. 34 failmsg="split moves empty field to end of expansion" 35 return 1 ;; 36 ( '7,::,\on\e,:\tw'\''o,\th\'\''re\e,:\\'\''fo\u\r:,:,:,U,U,U,U,U,' ) 37 # ksh93 with a DEBUG trap set 38 failmsg="non-whitespace ignored in split" 39 return 1 ;; 40 ( '1, :: \on\e :\tw'\''o \th\'\''re\e :\\'\''fo\u\r: : : ,U,U,U,U,U,U,U,U,U,U,U,' ) 41 failmsg="no split (native zsh?)" 42 return 1 ;; 43 ( * ) return 1 ;; 44 esac 45ENDT 46 47TEST title='tolower (ASCII)' 48 v=ABCDEFGHIJKLMNOPQRSTUVWXYZ 49 tolower v 50 str eq $v abcdefghijklmnopqrstuvwxyz 51ENDT 52 53TEST title='toupper (ASCII)' 54 v=abcdefghijklmnopqrstuvwxyz 55 toupper v 56 str eq $v ABCDEFGHIJKLMNOPQRSTUVWXYZ 57ENDT 58 59TEST title='tolower (UTF-8)' 60 utf8Locale || return 61 v='ABCDÉFIJN_ΑΒΓΔΕΖ_АБВГДЕ_ԱԲԳԴԵԶ' 62 tolower v 63 case $v in 64 ( 'abcdéfijn_αβγδεζ_абвгде_աբգդեզ' ) 65 not isset MSH_2UP2LOW_NOUTF8 ;; 66 ( 'abcdÉfIJn_ΑΒΓΔΕΖ_АБВГДЕ_ԱԲԳԴԵԶ' ) 67 xfailmsg='no UTF-8' 68 isset MSH_2UP2LOW_NOUTF8 && return 2 ;; 69 ( * ) return 1 ;; 70 esac 71ENDT 72 73TEST title='toupper (UTF-8)' 74 utf8Locale || return 75 v='abcdéfijn_αβγδεζ_абвгде_աբգդեզ' 76 toupper v 77 case $v in 78 ( 'ABCDÉFIJN_ΑΒΓΔΕΖ_АБВГДЕ_ԱԲԳԴԵԶ' ) 79 not isset MSH_2UP2LOW_NOUTF8 ;; 80 ( 'ABCDéFijN_αβγδεζ_абвгде_աբգդեզ' ) 81 xfailmsg='no UTF-8' 82 isset MSH_2UP2LOW_NOUTF8 && return 2 ;; 83 ( * ) return 1 ;; 84 esac 85ENDT 86 87TEST title='backslash in nonexpanding here-document' 88 command eval 'v=$(thisshellhas BUG_HDOCMASK && umask 077 89 cat <<-\EOT'$CCn$CCt'abc \'$CCn$CCt'def \\'$CCn$CCt'ghi' \ 90 '\\\'$CCn$CCt'jkl \\\\'$CCn$CCt'end'$CCn$CCt'EOT'$CCn$CCt')' 91 case $v in 92 ( 'abc \'$CCn'def \\'$CCn'ghi \\\'$CCn'jkl \\\\'$CCn'end' ) 93 mustNotHave BUG_CSNHDBKSL ;; 94 ( 'abc '$CCt'def \\'$CCn'ghi \\'$CCt'jkl \\\\'$CCn'end' \ 95 | 'abc '$CCt'def \'$CCt'ghi \\'$CCt'jkl \\\'$CCt'end' ) # bash 2 and 3; bash 4.4 96 mustHave BUG_CSNHDBKSL ;; 97 ( * ) return 1 ;; 98 esac 99ENDT 100 101TEST title='single-quoted pattern in param subst' 102 v="${CCn}one${CCt}two'three/four'five" 103 case "${v#${CCn}'one'${CCt}'two'\''three'}" in 104 ( "/four'five" ) 105 mustNotHave BUG_PSUBSQUOT ;; 106 ( "$v" ) 107 mustHave BUG_PSUBSQUOT ;; 108 ( * ) return 1 ;; 109 esac 110ENDT 111 112TEST title='quoting within param subst in here-doc' 113 114 v=$(thisshellhas BUG_HDOCMASK && umask 077 115 unset -v S U foo bar 116 S=set 117 # Of the test expansions below, only ${S#"se"}, ${S%"et"}, ${S##"se"} and ${S%%"et"} 118 # have defined behaviour under POSIX (the double quotes must be removed). 119 { read -r foo; read -r bar; } <<-EOF 120 ${U-"1"}${U-'2'}${U:-"3"}${U:-'4'}${S+"5"}${S+'6'}${S:+"7"}${S:+'8'} 121 ${S#"se"}${S#'se'}${S%"et"}${S%'et'}${S##"se"}${S##'se'}${S%%"et"}${S%%'et'} 122 EOF 123 putln $foo$bar) 124 125 case $v in 126 ( \"1\"\'2\'\"3\"\'4\'\"5\"\'6\'\"7\"\'8\'ttssttss \ 127 | \"1\"\'2\'\"3\"\'4\'\"5\"\'6\'\"7\"\'8\'tsetssettsetsset ) 128 # 1. FreeBSD sh; 2. bosh 129 mustHave QRK_HDPARQUOT ;; 130 ( 12345678ttssttss \ 131 | 1\'2\'3\'4\'5\'6\'7\'8\'ttssttss \ 132 | 1\'2\'3\'4\'5\'6\'7\'8\'tsetssettsetsset ) 133 # 1. yash; 2. bash, dash, ksh93, zsh; 3. pdksh/mksh/lksh 134 mustNotHave QRK_HDPARQUOT ;; 135 ( * ) failmsg="unknown quirk/bug [$foo$bar]" 136 return 1 ;; 137 esac 138ENDT 139 140TEST title="trimming of IFS whitespace by 'read'" 141 142 v=$(thisshellhas BUG_HDOCMASK && umask 077 143 # (NOTE: in here-document below: two leading spaces and two trailing spaces!) 144 IFS=' ' read foo <<-EOF 145 ab cd 146 EOF 147 putln $foo) 148 149 case $v in 150 ( 'ab cd' ) 151 mustNotHave BUG_READWHSP ;; 152 ( 'ab cd ' ) 153 mustHave BUG_READWHSP ;; # dash 0.5.7, 0.5.8 154 ( * ) failmsg="[$v]" 155 return 1 ;; 156 esac 157ENDT 158 159TEST title='line continuation in expanding here-doc' 160 FIN() { 161 : 162 } 163 command eval 'v=$(thisshellhas BUG_HDOCMASK && umask 077 164 cat <<-FIN'$CCn$CCt'def \'$CCn$CCt'ghi'$CCn$CCt'jkl\'$CCn$CCt'FIN'$CCn$CCt'FIN'$CCn')' 165 unset -f FIN 166 case $v in 167 ( 'def '$CCt'ghi'$CCn'jkl'$CCt'FIN' ) 168 mustNotHave BUG_HDOCBKSL ;; 169 ( 'def ghi'$CCn'jkl' ) # zsh up to 5.4.2 170 mustHave BUG_HDOCBKSL ;; 171 ( * ) return 1 ;; 172 esac 173ENDT 174 175TEST title='double quotes properly deactivate glob' 176 case \\foo in 177 ( "\*" ) 178 case \\fx in 179 ( "\?x" ) 180 mustHave BUG_DQGLOB ;; 181 ( * ) failmsg='unknown variant of BUG_DQGLOB' 182 return 1 ;; 183 esac ;; 184 ( "\foo" ) 185 mustNotHave BUG_DQGLOB ;; 186 ( * ) return 1 ;; 187 esac 188ENDT 189 190TEST title='trim quoted pattern in here-doc' 191 v=ababcdcd 192 v=$(thisshellhas BUG_HDOCMASK && umask 077 193 cat <<-EOF 194 ${v#*ab},${v##*ab},${v%cd*},${v%%cd*} 195 ${v#*\a\b},${v##*\ab},${v%c\d*},${v%%\c\d*} 196 ${v#*"ab"},${v##*"a"b},${v%c"d"*},${v%%"cd"*} 197 ${v#*'ab'},${v##*'a'b},${v%c'd'*},${v%%'cd'*} 198 EOF 199 ) 200 vOK=abcdcd,cdcd,ababcd,abab 201 vBUG=ababcdcd,ababcdcd,ababcdcd,ababcdcd 202 case $v in 203 ( "$vOK$CCn$vOK$CCn$vOK$CCn$vOK" ) 204 mustNotHave BUG_PSUBSQHD ;; 205 ( "$vOK$CCn$vOK$CCn$vOK$CCn$vBUG" ) 206 mustHave BUG_PSUBSQHD ;; 207 ( * ) return 1 ;; 208 esac 209ENDT 210 211TEST title='here-doc can be read regardless of umask' 212 # note: 'umask 777' is active in the test suite: zero perms 213 { 214 command : <<-EOF 215 EOF 216 } 2>/dev/null 217 case $? in 218 ( 0 ) mustNotHave BUG_HDOCMASK ;; 219 ( * ) mustHave BUG_HDOCMASK ;; 220 esac 221ENDT 222 223TEST title='newlines from expansion in param subst' 224 # Note that AT&T ksh93 does not nest quotes in parameter substitutions, so some 225 # inner parts are unquoted on that shell; but the test runs with split and glob 226 # disabled, so it's irrelevant. Another gotcha eliminated by 'use safe'. 227 unset -v v 228 for v in \ 229 ${v-abc${CCn}def${CCn}ghi} \ 230 ${v-abc"${CCn}"def"${CCn}"ghi} \ 231 ${v-"abc${CCn}def${CCn}ghi"} \ 232 ${v-"abc"${CCn}"def"${CCn}"ghi"} \ 233 "${v-abc${CCn}def${CCn}ghi}" \ 234 "${v-abc"${CCn}"def"${CCn}"ghi}" \ 235 "${v-"abc${CCn}def${CCn}ghi"}" \ 236 "${v-"abc"${CCn}"def"${CCn}"ghi"}" 237 do 238 case $v in 239 ( abc${CCn}def${CCn}ghi ) ;; 240 ( * ) return 1 ;; 241 esac 242 done 243ENDT 244 245TEST title='literal newlines in param subst' 246 # Same test as the previous one, but with literal newlines. 247 # Wrap in subshell and 'eval' for BUG_PSUBNEWLN compatibility. 248 unset -v v 249 ( eval 'for v in \ 250 ${v-abc 251def 252ghi} \ 253 ${v-abc" 254"def" 255"ghi} \ 256 ${v-"abc 257def 258ghi"} \ 259 ${v-"abc" 260"def" 261"ghi"} \ 262 "${v-abc 263def 264ghi}" \ 265 "${v-abc" 266"def" 267"ghi}" \ 268 "${v-"abc 269def 270ghi"}" \ 271 "${v-"abc" 272"def" 273"ghi"}" 274 do 275 case $v in 276 ( abc${CCn}def${CCn}ghi ) ;; 277 ( * ) exit 147 ;; 278 esac 279 done' ) 2>/dev/null 280 case $? in 281 ( 0 ) ;; 282 ( 147 ) # syntax was parsed, but check failed 283 return 1 ;; 284 ( * ) # syntax error 285 mustHave BUG_PSUBNEWLN ;; 286 esac 287ENDT 288 289TEST title='additive string assignment' 290 v=foo 291 { v=$( MSH_NOT_FOUND_OK=y 292 v+=bar$v 2>/dev/null 293 putln $v 294 ); } 295 case $v in 296 ( foo ) mustNotHave ADDASSIGN && return 3;; 297 ( foobarfoo ) 298 mustHave ADDASSIGN ;; 299 ( * ) return 1 ;; 300 esac 301ENDT 302 303TEST title='glob patterns work for all values of IFS' 304 push IFS 305 IFS='?*[]' # on bash < 4.4, BUG_IFSGLOBC now breaks 'case' and hence all of modernish 306 case foo in 307 ( ??? ) case foo in 308 ( * ) case foo in 309 ( *[of]* ) 310 pop IFS 311 mustNotHave BUG_IFSGLOBC 312 return ;; 313 esac ;; 314 esac ;; 315 esac 316 IFS='no glob chars' # unbreak modernish on bash < 4.4 before popping 317 pop IFS 318 mustHave BUG_IFSGLOBC 319ENDT 320 321TEST title='multibyte UTF-8 char can be IFS char' 322 utf8Locale || return 323 324 # test field splitting 325 push IFS 326 IFS='£' # £ = C2 A3 327 v='abc§def ghi§jkl' # § = C2 A7 (same initial byte) 328 set -- $v 329 pop IFS 330 v=${#},${1-},${2-},${3-} 331 case $v in 332 ( '1,abc§def ghi§jkl,,' ) 333 ;; # continue below 334 ( * ) w=$(printf '\247') # second byte of § (A7) 335 case $v in 336 ( "1,abc${w}def ghi${w}jkl,," | "3,abc,${w}def ghi,${w}jkl" ) # ksh93 | mksh, FreeBSD sh 337 mustHave WRN_MULTIBYTE 338 ne v=$? 1 && return $v 339 mustHave BUG_MULTIBIFS 340 return ;; 341 ( * ) return 1 ;; 342 esac ;; 343 esac 344 345 # test "$*" 346 push IFS 347 IFS='§' 348 set -- 'abc' 'def ghi' 'jkl' 349 v="$*" # BUG_PP_* compat: quote 350 pop IFS 351 case $v in 352 ( 'abc§def ghi§jkl' ) 353 mustNotHave WRN_MULTIBYTE && mustNotHave BUG_MULTIBIFS ;; 354 ( abc?def\ ghi?jkl ) 355 mustHave WRN_MULTIBYTE 356 ne v=$? 1 && return $v 357 mustHave BUG_MULTIBIFS ;; 358 ( * ) return 1 ;; 359 esac 360ENDT 361 362TEST title='${var+set}' 363 r= 364 unset -v v 365 for i in 1 2 3 4; do 366 case ${v+s} in 367 ( s ) r=${r}s; unset -v v ;; 368 ( '' ) r=${r}u; v= ;; 369 esac 370 done 371 case $r in 372 (uuuu) mustHave BUG_ISSETLOOP ;; 373 (usus) mustNotHave BUG_ISSETLOOP ;; 374 ( * ) return 1 ;; 375 esac 376ENDT 377 378TEST title='${var:+nonempty}' 379 r= 380 v= 381 for i in 1 2 3 4; do 382 case ${v:+n} in 383 ( n ) r=${r}n; v= ;; 384 ( '' ) r=${r}e; v=foo ;; 385 esac 386 done 387 case $r in 388 (enen) ;; 389 ( * ) return 1 ;; 390 esac 391ENDT 392 393TEST title='${var-unset}' 394 r= 395 unset -v v 396 for i in 1 2 3 4; do 397 case ${v-u} in 398 ( '' ) r=${r}s; unset -v v ;; 399 ( u ) r=${r}u; v= ;; 400 esac 401 done 402 case $r in 403 (usus) ;; 404 ( * ) return 1 ;; 405 esac 406ENDT 407 408TEST title='${var:-empty}' 409 r= 410 v= 411 for i in 1 2 3 4; do 412 case ${v:-e} in 413 ( n ) r=${r}n; v= ;; 414 ( e ) r=${r}e; v=n ;; 415 esac 416 done 417 case $r in 418 (enen) ;; 419 ( * ) return 1 ;; 420 esac 421ENDT 422 423TEST title="pattern is not matched as literal string" 424 case [abc] in 425 ( [abc] ) 426 case [0-9] in 427 ( [0-9] ) 428 case [:alnum:] in 429 ( [:alnum:] ) 430 mustHave BUG_CASELIT 431 return ;; 432 esac ;; 433 esac ;; 434 esac 435 mustNotHave BUG_CASELIT 436ENDT 437 438TEST title="'case' matches escaped literal ctl chars" 439 # bash 2.05b, 3.0 and 3.1 have bugs with literal $CC01 and $CC7F, but test them all 440 # (except linefeed which signifies line continuation so would be removed when escaped). 441 IFS= 442 for v in $CC02 $CC03 $CC04 $CC05 $CC06 $CC07 $CC08 $CC09 $CC0B $CC0C $CC0D $CC0E $CC0F \ 443 $CC10 $CC11 $CC12 $CC13 $CC14 $CC15 $CC16 $CC17 $CC18 $CC19 $CC1A $CC1B $CC1C $CC1D $CC1E $CC1F 444 do 445 eval 'case ${CC01}a${CC7F}b${v}X${CC01}c${CC7F} in' \ 446 "( \\${CC01}\\a\\${CC7F}\\b\\${v}\\X\\${CC01}\\c\\${CC7F} )" \ 447 ' ;;' \ 448 '( * ) return 1 ;;' \ 449 'esac' 450 done 451ENDT 452 453TEST title="'case' handles empty bracket expressions" 454 # Empty bracket expressions such as [] or v=; [$v] should always be a non-match. 455 # FTL_EMPTYBRE causes [] | [] to be taken as a single bracket expression: ["] | ["]. 456 case ] in 457 ( [] | [] ) 458 failmsg=FTL_EMPTYBRE; return 1 ;; 459 ( []] ) ;; 460 ( * ) return 1 ;; 461 esac 462ENDT 463 464TEST title="'case' handles unbalanced parenthesis" 465 v=ini 466 { v=$( eval 'v=$( 467 case $v in 468 foo ) /dev/null/bar ;; 469 ( baz ) /dev/null/quux ;; 470 ini ) putln OK ;; 471 * ) putln WRONG ;; 472 esac 473 )' 474 putln $v 475 ); } 2>/dev/null 476 case $v in 477 ( OK ) mustNotHave BUG_CASEPAREN ;; 478 ( ini ) mustHave BUG_CASEPAREN ;; 479 ( * ) failmsg="v=$v"; return 1 ;; 480 esac 481ENDT 482 483TEST title='bracket expressions support char classes' 484 case / in 485 ( [[:punct:]] ) 486 mustNotHave BUG_NOCHCLASS ;; 487 ( * ) mustHave BUG_NOCHCLASS ;; 488 esac 489ENDT 490 491TEST title='quoted param expansion handles escaped }' 492 unset -v v 493 v="${v-ab\}cd\}ef\}gh}" 494 case $v in 495 ( 'ab\}cd\}ef\}gh' ) 496 mustHave BUG_PSUBBKSL1 ;; 497 ( 'ab}cd}ef}gh' ) 498 mustNotHave BUG_PSUBBKSL1 ;; 499 ( * ) return 1 ;; 500 esac 501ENDT 502 503TEST title='shell assignments are independent of IFS' 504 IFS="d ${CC01}b${CCt}c${CCn}d" 505 v=d${CCn}c${CC01}b${CCt}a 506 v=$v # trigger BUG_ASGNCC01 507 IFS= 508 case $v in 509 ( d${CCn}c${CC01}b${CCt}a ) 510 mustNotHave BUG_ASGNCC01 ;; 511 ( d${CCn}cb${CCt}a ) 512 mustHave BUG_ASGNCC01 ;; 513 ( * ) return 1 ;; 514 esac 515ENDT 516 517TEST title='empty removal of unqoted unset variables' 518 v=a 519 w= 520 unset -v x 521 set +u 522 IFS= 523 # test nonempty (v), empty (w), and unset (x) variables 524 set $v ${v-} ${v:-} ${v+$v} ${v:+$v} $w ${w-} ${w:-} ${w+$w} ${w:+$w} $x ${x-} ${x:-} ${x+$x} ${x:+$x} 525 IFS=, 526 v="$*" 527 IFS= 528 set -u 529 case $v in 530 ( 'a,a,a,a,a' ) 531 mustNotHave BUG_PSUBEMPT ;; 532 ( 'a,a,a,a,a,,,' ) 533 mustHave BUG_PSUBEMPT ;; 534 ( * ) return 1 ;; 535 esac 536ENDT 537 538TEST title="assignment in parameter substitution" 539 # Regression test for BUG_PSUBASNCC. 540 unset -v foo bar 541 set -- ${foo=$ASCIICHARS} "${bar=$ASCIICHARS}" 542 # check that the assignment succeeds 543 str eq $foo$bar $ASCIICHARS$ASCIICHARS || return 1 544 # check that the parameter substitution returns identical results 545 if str eq $1$2 $ASCIICHARS$ASCIICHARS; then 546 mustNotHave BUG_PSUBASNCC 547 return 548 fi 549 # if not, check for BUG_PSUBASNCC 550 foo=$ASCIICHARS; replacein foo $CC01 ''; replacein foo $CC7F '' 551 bar=$ASCIICHARS; replacein bar $CC01 '' 552 str eq $1,$2 $foo,$bar && mustHave BUG_PSUBASNCC 553ENDT 554 555TEST title="str lt/gt: sorts before/after" 556 str lt abcd efgh && str gt EFGH ABCD 557ENDT 558 559TEST title="closing brace does not terminate string" 560 # this was a bug in dash-git, fixed in commit 878514712c5 561 v=vvv 562 v=12${#v}45 563 str eq $v 12345 564ENDT 565 566TEST title='${v#P*}, ${v##P*}, ${v%*P}, ${v%%*P}' 567 v=barbarfoofoo 568 v=${v#bar*},${v##bar*},${v%*foo},${v%%*foo} 569 case $v in 570 ( 'barfoofoo,,barbarfoo,' ) 571 ;; 572 ( * ) return 1 ;; # FTL_PSUB (yash 2.19-2.39) 573 esac 574ENDT 575 576TEST title='splitting ${var#foo}, non-whitespace' 577 v="foo!one!two!three" 578 v=$(IFS="!"; printf '%s@' ${v#foo} ${v##foo}) 579 case $v in 580 ( '@@one@two@three@@@one@two@three@' ) 581 mustHave BUG_PSUBIFSNW ;; 582 ( '@one@two@three@@one@two@three@' ) 583 mustNotHave BUG_PSUBIFSNW ;; 584 ( * ) failmsg=$v; return 1 ;; 585 esac 586ENDT 587 588TEST title='splitting ${var#foo}, whitespace' 589 v="foo${CCt}one${CCt}two${CCt}three" 590 v=$(IFS=$CCt; printf '%s@' ${v#foo} ${v##foo}) 591 case $v in 592 ( '@one@two@three@@one@two@three@' ) 593 mustHave BUG_PSUBIFSWH ;; 594 ( 'one@two@three@one@two@three@' ) 595 mustNotHave BUG_PSUBIFSWH ;; 596 ( * ) failmsg=$v; return 1 ;; 597 esac 598ENDT 599 600TEST title='splitting ${var%foo}, non-whitespace' 601 v="XabXcdXefX" 602 v=$(IFS="X"; printf '%s@' ${v%efX} ${v%%efX}) 603 case $v in 604 ( '@@ab@cd@@@ab@cd@' ) 605 mustNotHave QRK_IFSFINAL && mustHave BUG_PSUBIFSNW ;; 606 ( '@ab@cd@@ab@cd@' ) 607 mustNotHave BUG_PSUBIFSNW && mustNotHave QRK_IFSFINAL ;; 608 ( '@ab@cd@@@ab@cd@@' ) 609 mustNotHave BUG_PSUBIFSNW && mustHave QRK_IFSFINAL ;; 610 ( * ) failmsg=$v; return 1 ;; 611 esac 612ENDT 613 614TEST title='splitting ${var%foo}, whitespace' 615 v="${CCn}ab${CCn}cd${CCn}ef${CCn}" 616 v=$(IFS=$CCn; printf '%s@' ${v%ef?} ${v%%ef?}) 617 case $v in 618 ( '@ab@cd@@ab@cd@' ) 619 mustHave BUG_PSUBIFSWH ;; 620 ( 'ab@cd@ab@cd@' ) 621 mustNotHave BUG_PSUBIFSWH ;; 622 ( * ) failmsg=$v; return 1 ;; 623 esac 624ENDT 625