I know there is a better way to do this.
What is the better way?
How do you do a string replace on a string variable in bash?
For Example: (using php because that's what I know)
$path = "path/to/directory/foo bar";
$path = str_replace(" ", "\ ", "$path");
echo $path;
returns:
path/to/directory/foo\ bar
To perform the specific replacement in bash
:
path='path/to/directory/foo bar'
echo "${path// /\\ }"
$
when assigning to variables in bash
.=
.path
is assigned with single quotes, whereas the string replacement occurs in double quotes - this distinction is important: bash
does NOT interpret single-quoted strings, whereas you can refer to variables (and do other things) in double-quoted strings; (also, not quoting a variable reference at all has other ramifications, often undesired - in general, double-quote your variable references)Explanation of string replacement "${path// /\\ }"
:
{...}
//
specifies that ALL occurrences of the following search pattern are to be replaced (use /
to replace the first occurrence only)./
separates the search pattern,
(a single space), from the replacement string, \\
.\
, must be represented as \\
, because \
has special meaning as an escape char. and must therefore itself be escaped for literal use.The above is an instance of what bash (somewhat cryptically) calls shell parameter expansion and also parameter expansion and [parameter and] variable expansion. There are many more flavors, such as for extracting a substring, providing a default value, stripping a prefix or suffix, ... - see the BashGuide page on the topic or the manual.
As for what types of expressions are supported in the search and replacement strings:
*.txt
); for instance, v='dear me'; echo "${v/m*/you}"
yields 'dear you'
. Note that the longest match will be used.
/
, as we've seen above, causes all matching occurrences of the pattern to be replaced - by default, only the first one is replaced.#
causes the rest of the pattern to only match at the beginning of the input variable%
only matches at the end
$(...)
, ...; e.g.:
v='sweet home'; echo "${v/home/$HOME}"
yields, for instance, 'sweet /home/jdoe'
.v='It is now %T'; echo "${v/\%T/$(date +%T)}"
yields, for instance, It is now 10:05:17
.o1=1 o2=3 v="$o1 + $o2 equals result"; echo "${v/result/$(( $o1 + $o2 ))}"
yields '1 + 3 equals 4'
(I think)There are many more features and subtleties - refer to the link above.
How about sed? Is that what you're looking for?
#!/bin/bash
path="path/to/directory/foo bar"
new_path=$(echo "$path" | sed 's/ /\\ /g')
echo "New Path: '$new_path"
But as @n0rd pointed out in his comment, is probably better just quoting the path when you want to use it; something like...
path="path/to/directory/foo bar"
echo "test" > "$path"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With