Anis_Stack
Anis_Stack

Reputation: 3452

how to replace "/" in a POSIX sh string

To replace substring in the bash string str I use:

str=${str/$pattern/$new}

However, I'm presently writing a script which will be executed with ash.

I have a string containing '/' and I want to use the above syntax inorder to replace the '/' in my string but it does not work.

I tried:

str=${str///a}
str=${str/\//a}
str=${str/'/'/a}

But they do not work

How I can fix that?

Upvotes: 16

Views: 7890

Answers (2)

Jaakko Salomaa
Jaakko Salomaa

Reputation: 146

POSIX string substitutions can be used to create a 100% POSIX compatible function that does the replacement. For short strings, this is considerably faster than command substitution, especially under Cygwin, whose fork(2) copies the parent process's address space on top of creating processes being generally slow in Windows.

replace_all() {
    RIGHT=$1
    R=

    while [ -n "$RIGHT" ]; do
        LEFT=${RIGHT%%$2*}

        if [ "$LEFT" = "$RIGHT" ]; then
            R=$R$RIGHT
            return
        fi

        R=$R$LEFT$3
        RIGHT=${RIGHT#*$2}
    done
}

It works like this:

$ replace_all ' foo bar baz ' ' ' .
$ echo $R
.foo.bar.baz.

With regards to performance, replacing 25% of characters in a 512 byte string runs roughly 50 times faster with replace_all() than command substitution under the Cygwin dash(1). However, the execution time evens out around 4 KiB.

Upvotes: 5

Charles Duffy
Charles Duffy

Reputation: 295687

This parameter expansion is a bash extension to POSIX sh. If you review the relevant section of IEEE standard 1003.1, you'll see that it isn't a required feature, so shells which promise only POSIX compliance, such as ash, have no obligation to implement it, and no obligation for their implementations to hew to any particular standard of correctness should they do so anyhow..

If you want bash extensions, you need to use bash (or other ksh derivatives which are extended similarly).

In the interim, you can use other tools. For instance:

str=$(printf '%s' "$str" | tr '/' 'a')

or

str=$(printf '%s' "$str" | sed -e 's@/@a@g')

Upvotes: 20

Related Questions