$ a="hello world"
$ echo ${a// /_}
hello_world
Según bash(1):
${parameter/pattern/string}
Sustitución de patrón. El patrón se expande para producir un patrón como en la expansión del nombre de la ruta. El parámetro se expande y la coincidencia más larga del patrón con su valor se reemplaza con una cadena. Si el patrón comienza con /, se reemplazan todas las coincidencias del patrón
con cuerda Normalmente solo se reemplaza la primera coincidencia. Si el patrón comienza con #, debe coincidir con el principio del valor expandido del parámetro. Si el patrón comienza con %, debe coincidir con el final del valor expandido del parámetro. Si la cadena es nula, se eliminan las coincidencias del patrón y se puede omitir el siguiente patrón. Si el parámetro es @ o *, la operación de sustitución se aplica a cada parámetro posicional por turno, y la expansión es la lista resultante. Si el parámetro es una variable de matriz con subíndice @ o *, la operación de sustitución se aplica a cada miembro de la matriz por turno, y la expansión es la lista resultante.
Podría intentar lo siguiente:
str="${str// /_}"