2

I have written the following script:

#!/bin/bash

TEST=$1
TEST_1=$2

if [[ "$TEST" == e ]];then
echo $TEST_1
else
echo "Input is not e"
fi

Now if I will run:

sh test.sh e NS3#$xX$56M

then output will be

NS3#56M

That's removing all the $xX$ charcters. Is there any way I can get the all characters including the special characters?

1 Answer 1

11

The reason is that you are not correctly quoting your input. The parameter you pass to the script contains $, and you pass the parameter unquoted (i.e. simply as NS3#$xX$56M), which means it will be subject to variable expansion. This means that the shell that interprets your

sh test.sh e NS3#$xX$56M

command to call the test.sh script will first try to substitute the $xX part with the content of a shell variable (either locally defined or exported as environment variable) xX, and - since there likely isn't any - substitutes this part with "nothing", before it passes the result to your script. However, this is the correct functioning of the shell, and hence there is nothing principally wrong with your script (as noted by @roaima).

To prevent this problem, enclose the string in single-quotes which will disable any expansions:

sh test.sh e 'NS3#$xX$56M'

As a general note on your script:

  • Don't use all-uppercase variable names unless you plan to export them to the environment (i.e. use test instead of TEST) - this prevents unwanted clashes between variables of your script and possibly essential environment variables.
  • Use shellcheck, also available as standalone program on many linux distributions, to "proof-read" your scripts; this will help prevent many errors.
  • As you saw from the problem you encountered, always be sure to correctly quote shell variables when using them, unless you positively know that you want variable/glob expansion and word splitting to happen. This also applies to the usage of shell variables in your script.
  • You call the script as
    sh test.sh ....
    
    This will override the #!-line and use the sh shell, which on many systems will be a POSIX-compliant shell that doesn't understand the [[ ... ]] operator e.g. Either make it executable and call it as ./test.sh, or explicitly use bash test.sh.
5
  • yes with single quote I can access the value correctly. But that special character string (NS3#$xX$56M) is passed at run time. So manually we cannot put quotes. In stead can we make some changes in side the script by which it wont trim those special characters
    – John
    Commented Jun 30, 2021 at 11:37
  • 7
    @John That's impossible. You can't recover NS3#$xX$56M from NS3#M. You need to fix whatever is calling the script with an invalid argument. Commented Jun 30, 2021 at 12:37
  • 5
    If the thing that calls your script is like system("sh test.sh " + someVar) then that system call may well be using /bin/sh to invoke the passed string, so you get sh -c 'sh test.sh NS3#$xX$56M'. See if you can do something like system(['bash', 'test.sh', someVar]) which will avoid the enclosing /bin/sh and leave the values intact. Commented Jun 30, 2021 at 13:33
  • @Gilles'SO-stopbeingevil' Do you have any idea under what conditions a shell would keep the $5 in the sample input verbatim? I would naively think that NS3#$xX$56M would become NS3#6M (and it does in my bash tests), but the OPs sample output seems to indicate that the "trailing" $ gets absorbed, too.
    – AdminBee
    Commented Jun 30, 2021 at 13:55
  • 2
    @John, there are serious security bugs implied if your code is just substituting input onto a command line -- think "one of the two ways Western Digital MyBooks are getting hacked this week" type serious bugs. Really, really don't use string concatenation to merge data into shell commands; whatever is doing that shouldn't ever be released to the wild, and you have more than enough grounds to insist that whatever team maintains that component fix it, even if it's not code you personally control yourself. Commented Jun 30, 2021 at 18:27

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.