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
Where Is Hardware Timer Interrupt
Merge PDF Files with Numerical Sort
Bash VS Csh VS Others - Which Is Better for Application Maintenance
Not Authorized for Query on Admin.System.Namespaces on Mongodb
Possible to Use a .Dll on Linux
How to Get Started Writing a Compositing Wm
How to Find or Calculate a Linux Process's Page Table Size and Other Kernel Accounting
How to Setup Oracle Odbc Drivers on Rhel 6/Linux
The Return Code from 'Grep' Is Not as Expected on Linux
Error: Ld.So: Object Ld_Preload Cannot Be Preloaded: Ignored
How to Write and Execute a Hello World Program in File for R
Gedit Syntax Highlighting for Assembler Files (*.Asm)
Difference Between Linux Loadable and Built-In Modules
@Reboot Is Not Working in Cron
Use Ssh to Start a Background Process on a Remote Server, and Exit Session