7 ms·
OK interesting, yeah I think dash is just plain broken ... $ dash -c 'echo "c:\\new"' c: ew $ busybox ash -c 'echo "c:\\new"' c:\new It re
by chubot 3mo ago
OK interesting, yeah I think dash is just plain broken ...
$ dash -c 'echo "c:\\new"'
c:
ew
$ busybox ash -c 'echo "c:\\new"'
c:\new
It requires 4 backslashes:
$ dash -c 'echo "c:\\\\new"'
c:\new
$ busybox ash -c 'echo "c:\\\\new"'
c:\\new
I am not sure this is a matter of "undefined behavior in POSIX" -- I think it might just be dash being wildly unconformant, which I have seen in other cases.
It's one of the least POSIX compliant shells. It is derived from the same codebase as busybox ash, but busybox receives more maintenance.
---
In any case, it is pretty sad that sh is in such poor shape than the default /bin/sh on Debian has different behavior in this basic case.
I built OSH to be a set of semantics agreed upon by many shells. I don't think any cross-shell test suites like our spec tests had existed in the past - https://oils.pub/release/0.37.0/quality.html https://oils.pub/release/0.37.0/quality.html
But there is little coordination among shell authors, and no real motivation to fix the gaps. In contrast, there is A LOT of coordination among JavaScript engine authors, mostly because there are people paid to work on them.
- dzaima 3mo agoOP links you to POSIX explicitly denoting it being implementation-defined - https://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_05 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/e..., and https://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/e... literally says "It is not possible to use echo portably across all POSIX systems unless [specific setup]" Interestingly, that doesn't allow implementation-defined behavior for "echo -e", for which bash does have special behavior.
- chubot 3mo agoOK interesting, I knew about the -e -n flags issue, which means that any portable shell script has to use printf, not echo. Didn't quite realize that the use of backslash also forces printf ... what a mess
- gaigalas 3mo agoHere's how I deal with it using feature detection: case "$({ printf %b "\\061" || print -r -- 2 || echo -n -e "\\063" || command -p printf %b "\\064"; } 2>/dev/null)" in 1) alias _printb1='printf %b' alias _printn1='printf %s' ;; 2) alias _printb1='print -n --' alias _printn1='print -nr --' ;; 3) alias _printb1='echo -n -e' alias _printn1='echo -n -E' ;; 4) _printb1 () { command -p printf '%b' "$1"; } _printn1 () { command -p printf '%s' "$1"; } ;; '-e 3') _pdash () { _pd=$1; while :; do case $_pd in -*) echo -n "\\055"; _pd=${_pd#-};; *) break;; esac; done; } _printb1 () { _pdash "$1"; echo -n "$_pd"; } _printn1 () { local _p _r _pdash "$1"; _r=$_pd while case $_r in *"$_BS"*) :;; *) false;; esac; do _p=${_r%%"$_BS"*} _r=${_r#*"$_BS"} echo -n "$_p$_BS$_BS" done _pdash "$_r"; _r=$_pd echo -n "$_r" } ;; *) exit 1;; esac 1) is for shells who have printf, 2) is for the ksh family, 4) is for PATH='' yash exclusively, -e 3) is for posh exclusively. It exports two callables, _printb1 and _printf1 that escape and don't escape backslashes respectively, are immune to trailing dash gotchas and other pitfalls. Unfortunatelly, not all shells allow overriding `echo` so I can't proper polyfill when necessary. I'm going to extremes here, but a simpler version of this can be used for the most popular shells.
- chubot 3mo agoI think that is basically the approach modernish uses: https://github.com/modernish/modernish https://github.com/modernish/modernish But it does feel complex to me. Personally I just write in the common subset of bash and OSH, which is very large. I never need to support say dash, since every machine that has dash also has bash, which is less broken in terms of 'echo' and so forth. bash has its own broken-ness, but running under OSH solves that. And OSH also supports some busybox idioms -- we learned last year that bash cannot run busybox ash scripts on Alpine e.g. 'chdir' is an alias for 'cd' in busybox, but not in bash. And Alpine scripts use it, so bash can't run Alpine scripts, but OSH can (as of last year).