String Replacement in Bash - Bad Substitution Error

String replacement in bash - bad substitution error

That substitution works fine in Bash 4.2.8 (and looks fine according to the documentation).

My best guess would be that you're not actually using Bash - how are you invoking the script? If you're doing sh script.sh you may well be running it with Dash or something similar (and Dash does indeed give a substitution error on line 3). Try explicitly running it with Bash (bash script.sh).

If it turns out you are actually using Dash, there's some useful information on the differences and how to go back to using Bash (if you want to) here: https://wiki.ubuntu.com/DashAsBinSh

Bash string replacement gives me bad substitution

URL="http://hostname/project/branches/Old_Branch/package"
SRC="Old_Branch"
REP="New_Branch"

echo "${URL/$SRC/$REP}"

Note no $ sigill for URL in ${} =)

bash : Bad Substitution

The default shell (/bin/sh) under Ubuntu points to dash, not bash.

me@pc:~$ readlink -f $(which sh)
/bin/dash

So if you chmod +x your_script_file.sh and then run it with ./your_script_file.sh, or if you run it with bash your_script_file.sh, it should work fine.

Running it with sh your_script_file.sh will not work because the hashbang line will be ignored and the script will be interpreted by dash, which does not support that string substitution syntax.

Bash: replacement of string with quotes (bad substitution error)

echo ${$line/coordinateIndex="0"/coordinateIndex="124"} 

should not have the $ inside:

echo ${line/coordinateIndex="0"/coordinateIndex="124"}

You may also need to quote it properly to properly match the double-quotes.

echo ${line/coordinateIndex=\"0\"/coordinateIndex="124"}

And it's also better to enclose your argument around double-quotes to prevent word splitting with values of IFS and unexpected pathname expansion:

echo "${line/coordinateIndex=\"0\"/coordinateIndex="124"}"

See more detail about usage of Parameter Expansion in the Bash Manual.

How to fix bad substitution error in bash?

Your error is:

echo "#include ${className.h}" >> $className.cpp`
^

It threats the whole className.h as the variable name, and the dot character. is not allowed in a variable name.

Also always add the -r flag to read, unless you want it to interpret escaping.

You can create your templates more clearly and efficiently with here-documents that expands bash variables values:

Although, in case you need to have an actual dollar sign $ literal, you need to escape it as \$, or bash will try to expand a variable name to its value.

#!/usr/bin/env bash

echo "Please enter the name of the class to be created"
read -r className

cat <<EndOfClassHeader >"$className.h"
#include <iostream>
#ifndef SICT_${className^^}_H
#define SICT_${className^^}_H
namespace sict {
class ${className^} {

public:
};
}
#endif
EndOfClassHeader

cat <<ENdOfClassCPP >"$className.cpp"
#include ${className}.h
#include <iostream>
using namespace sict;
using namespace std;
namespace sict {
}
ENdOfClassCPP

Bash script substring on $(pwd)? Bad substitution error

You are getting confused between command substitution with parameter substitution.

In your particular situation you will need to read the command substitution of pwd into a variable first and then use that for parameter expansion and so:

pworkd=$(pwd)
echo ${$(pworkd):2}

Getting bad substitution error in shell script

You misplaced a bracket: {$COUNTRY}_POPULATION should be ${COUNTRY}_POPULATION. But even then it would not work as you expect. Use bash indirect expansion:

$ name="${COUNTRY}_POPULATION"
$ echo "${!name}"
5,00,00,000

Or, if you have bash version >= 4.3, you can also use a refname:

$ declare -n name="${COUNTRY}_POPULATION"
$ echo "$name"
5,00,00,000

bash: bash script gives Bad substitution error

The correct syntax is:

url=$(cat /var/scripts/test.txt | grep -oP '(?<=display_url":")[^"]+')

That being said, to avoid Useless Use Of Cat, try this:

url=$(grep -oP '(?<=display_url":")[^"]+' /var/scripts/test.txt)

From man bash:

Command Substitution
Command substitution allows the output of a command to replace the command name.
There are two forms:

          $(command)
or
`command`

String replacement (to lowercase) in Bash 4.3.33 - bad substitution error

Looks like the bash that is first in PATH happens to be 4.3.33, but the bash you're running in the interactive session is probably an older version. Run echo "$BASH_VERSION" to check.

If the above is correct, run

type bash

to see the path of the newer version, probably something like /opt/local/bin/bash. I'll assume it is. If you want that to be your login shell, first add it to /etc/shells

sudo -e /etc/shells

After that, users are allowed to select that as their login shell by using the chsh (change shell) command

chsh -s /opt/local/bin/bash

shell string bad substitution

If your shell is a sufficiently recent version of bash, that parameter expansion notation should work.

In many other shells, it will not work, and a bad substitution error is the way the shell says 'You asked for a parameter substitution but it does not make sense to me'.


Also, given the script:

#! /bin/sh
length=echo `expr index "$1" .zip`
a=$1
echo $(a:0:length}

The second line exports variable length with value echo for the command that is generated by running expr index "$1" .zip. It does not assign to length. That should be just:

length=$(expr index "${1:?}" .zip)

where the ${1:?} notation generates an error if $1 is not set (if the script is invoked with no arguments).

The last line should be:

echo ${a:0:$length}

Note that if $1 holds filename.zip, the output of expr index $1 .zip is 2, because the letter i appears at index 2 in filename.zip. If the intention is to get the base name of the file without the .zip extension, then the classic way to do it is:

base=$(basename $1 .zip)

and the more modern way is:

base=${1%.zip}

There is a difference; if the name is /path/to/filename.zip, the classic output is filename and the modern one is /path/to/filename. You can get the classic output with:

base=${1%.zip}
base=${base##*/}

Or, in the classic version, you can get the path with:

base=$(dirname $1)/$(basename $1 .zip)`.)

If the file names can contain spaces, you need to think about using double quotes, especially in the invocations of basename and dirname.



Related Topics



Leave a reply



Submit