The pdksh shell, which is the default shell for new users on e.g. OpenBSD, does not have the non-standard parameter substitution that you mention.
To replace all non-overlapping matches of some pattern with some new string, you may use sed:
str=$( printf '%s\n' "$str" | sed 's/PATTERN/REPLACEMENT/g' )
Note that this uses PATTERN as a POSIX basic regular expression, that REPLACEMENT must escape &, \1 and other strings that sed will interpret in special ways, and that the command substitution strips all trailing newline characters from the end of the string.
Example:
$ str=@title/section1/section2 $ str=$( printf '%s\n' "$str" | sed 's/\//-/g' ) $ printf '%s\n' "$str" @title-section1-section2
In this case, when only a single character is being replaced, one could replace the sed substitution with y/\//-/, or replace the whole sed command with the tr command tr / -.
You may also choose to write a shell loop:
while true; do case $str in *PATTERN*) str=${str%%PATTERN*}REPLACEMENT${str#*PATTERN} ;; *) break esac done
In this code, PATTERN is a shell pattern ("filename globbing pattern"). The code repeatedly replaces the first match of the pattern in the string with the replacement string, until there are no more matches. Because of the loop, there is no guarantee that later iterations do not perform replacements in previously inserted replacement strings.
Example:
$ str=@title/section1/section2 $ while true; do case $str in (*/*) str=${str%%/*}-${str#*/} ;; (*) break; esac; done $ printf '%s\n' "$str" @title-section1-section2
ksh, butecho ${str/\//-}worked as expected, note there is only one/afterstr.ksh -c 'str="@test/string"; echo "${str//\//-}"'prints@test-string.str=aba; echo "${str/a/x}"; echo "${str//a/x}"pdkshis actively developed on OpenBSD. It's not a bug that a shell does not implement a non-standard parameter substitution. It's unclear what the "mistakes" that were corrected refers to in the changelog.${str//@}for some reason