#!/bin/sh # Banco POSIX para candidatos a /bin/sh (SDD: docs/plan-botar-busybox.md §paso 3). # Uso: scripts/sh-banco-posix.sh # 57 casos POSIX ejecutados con `$SH -c`. Baseline medido 2026-09-21: busybox sh 56/57, # brush 0.4.0 56/57 (diverge sólo en `shift` más allá de $#: devuelve 2, POSIX/busybox 1). # NO es una prueba de suficiencia: el banco pasa y aun así brush no construye autotools. SH="$1"; [ -n "$SH" ] || { echo "uso: $0 "; exit 2; } ok=0; ko=0; KOLIST="" t() { # t nombre="$1"; esperado="$2"; codigo="$3" got=$("$SH" -c "$codigo" 2>&1) if [ "$got" = "$esperado" ]; then ok=$((ok+1)) else ko=$((ko+1)); KOLIST="$KOLIST ✗ $nombre esperado: [$esperado] obtenido: [$got]" fi } t "echo" "hola" 'echo hola' t "pipeline" "2" 'printf "a\nb\n" | wc -l | tr -d " "' t "redireccion" "x" 'echo x > /tmp/_p1 && cat /tmp/_p1' t "aqui-doc" "linea" 'cat </dev/null; [ $? -ne 0 ] && echo 0' t "expansion-largo" "3" 'v=abc; echo ${#v}' t "quita-sufijo" "arch" 'v=arch.tar.gz; echo ${v%%.*}' t "quita-prefijo" "gz" 'v=arch.tar.gz; echo ${v##*.}' t "aritmetica" "7" 'echo $((3+4))' t "aritmetica-var" "6" 'x=2; echo $((x*3))' t "test-corchete" "si" '[ 1 -lt 2 ] && echo si' t "test-cadena" "si" '[ "a" = "a" ] && [ -n "a" ] && echo si' t "posicionales" "a:b:c" 'set -- a b c; IFS=:; echo "$*"' t "todos-arroba" "a b c" 'set -- a b c; echo "$@"' t "shift" "c" 'set -- a b c; shift 2; echo $1' t "getopts" "v=1 f=x" 'set -- -v -f x; v=0; while getopts vf: o; do case $o in v) v=1;; f) f=$OPTARG;; esac; done; echo "v=$v f=$f"' t "source-punto" "sourced" 'echo "echo sourced" > /tmp/_p2; . /tmp/_p2' t "subshell-aisla" "fuera" 'x=fuera; ( x=dentro ); echo $x' t "trap-exit" "adios" 'trap "echo adios" EXIT; true' t "set-e-corta" "antes" 'set -e; echo antes; false; echo despues' t "set-u" "0" 'set -u; ( echo $NODEF ) 2>/dev/null; [ $? -ne 0 ] && echo 0' t "exec-redir" "z" 'exec 3>/tmp/_p3; echo z >&3; exec 3>&-; cat /tmp/_p3' t "glob" "si" 'mkdir -p /tmp/_g && : > /tmp/_g/f1 && for f in /tmp/_g/f*; do [ -e "$f" ] && echo si; done' t "glob-sin-match" "/tmp/_nada*" 'for f in /tmp/_nada*; do echo $f; done' t "IFS-split" "a b c" 'IFS=,; set -- $(echo "a,b,c"); IFS=" "; echo "$*"' t "comillas-preservan" "a b" 'x="a b"; echo "$x"' t "sin-comillas-parte" "a b" 'x="a b"; echo $x' t "escape-barra" 'a\b' 'printf "%s\n" "a\\b"' t "printf-formato" "007" 'printf "%03d\n" 7' t "read-var" "dato" 'echo dato | { read v; echo $v; }' t "eval" "ev" 'c="echo ev"; eval $c' t "dollar-dollar" "si" '[ -n "$$" ] && echo si' t "PATH-busca" "si" 'command -v echo >/dev/null && echo si' t "anidado-sust" "ab" 'echo "$(echo a)$(echo b)"' t "multi-cmd-punto-coma" "a b" 'echo -n "a "; echo b' t "negacion" "si" 'if ! false; then echo si; fi' t "bucle-until" "3" 'i=0; until [ $i -ge 3 ]; do i=$((i+1)); done; echo $i' t "break-continue" "1 3" 'r=; for i in 1 2 3 4; do [ $i = 2 ] && continue; [ $i = 4 ] && break; r="$r $i"; done; echo ${r# }' t "return-funcion" "7" 'f() { return 7; }; f; echo $?' t "here-string-noposix" "SKIP" 'echo SKIP' t "wait-bg" "si" '(sleep 0.05) & wait; echo si' t "unset-func" "si" 'f() { echo no; }; unset -f f; command -v f >/dev/null || echo si' t "export-hijo" "val" 'export V=val; "'"$SH"'" -c "echo \$V"' t "shift-sin-args" "1" 'set --; shift 2>/dev/null; echo $?' echo "$SH: OK=$ok FALLO=$ko" [ -n "$KOLIST" ] && echo "$KOLIST" exit $ko