0

I have child script which will source the main script and will pass the argument to the Function available in Main script and execute the function definition. Function call is working fine for me, but i'm facing the below issues

  1. First echo statement is not getting printed

  2. Variable now is not getting resolved in child script argument

    Please find my findings below.

Main Script

Function_1 ()
{
cd /home/test/

File_name="$1".txt

if [[ "$File_name" =~ ^[[:alnum:]][[$_."#&']] ]]; then echo " For your Info, File name can be alpha numeric and can contain special characters like $_."&'#" please proceed " fi

if [[ -f "$File_name" ]]; then echo "File Name - $File_name" else echo "File Name - $File_name doesn't exists" fi

}

Child Script

export now=$( date '+%Y%m%d' )
Function_1 'abc_${now}' 

Expected result

For your Info, File name can be alpha numeric and can contain special characters like $_."&'#" please proceed 
File Name - abc_20200204.txt

Actual result

File Name - abc_$now.txt doesn't exists
  • 3
    Single quotes in Function_1 'abc_${now}' will prevent variable expansion. – muru Feb 04 '20 at 08:40
  • In addition, are you sure your regular expression pattern works as expected? Even when syntactically corrected (why the two square brackets around your character list containing the special characters?), it would appear to only match filenames that start with exactly one alphanumerical character and then exactly one of the special characters ... – AdminBee Feb 04 '20 at 10:33
  • @muru: Ya is there any to resolve the variable within single quotes ? – user78873 Feb 04 '20 at 12:38
  • @AdminBee: Ya I have tried removing the two square brackets and remaining special characters works as expected. Even the regular expression "$File_name" =~ ^[[:alnum:]][[$_."#&']] is accepting multiple underscore _ in file name. For issue-2 is there any way to resolve the variable within single quotes. – user78873 Feb 04 '20 at 12:41
  • On issue 2: do you absolutely need single quotes? If variable substitution is wanted, double quotes " ... " should do what you want. Here is a good reference on quoting in bash. – AdminBee Feb 04 '20 at 12:55
  • @AdminBee: Can you post it as a answer ?? its working out for me so that i can accept your answer .. Could you please let me know if there is a way to achieve the same in single quotes '....' – user78873 Feb 06 '20 at 03:20

2 Answers2

2
if [[ "$File_name" =~ ^[[:alnum:]][[$_."#&']] ]]; then

You are using a " and a ' due to which the expression is incomplete, and getting failed.

Abishek J
  • 170
0

I think the problems you experienced can in general be attributed to the handling of special characters and quoting in your shell script.

As a leading remark: you didn't mention how your child script gets access to the functions in the main script, but I assume you do something like

~$ source main_script.sh
~$ export now=$( date '+%Y%m%d' )
~$ Function_1 'abc_${now}'

If I do so, my shell complains about several syntax errors, and the script wouldn't work. I assume you also use the bash since you used that tag, and I admit that I am surprised you did not encounter these errors. You may still want to consider using a tool like shellcheck, available online or as software package in many Linux distributions, to verify your shell-scripts - it certainly helps me finding typos and the like.

Now to the issues you encountered.

You state that the first echo output never occurs. I think this is related to the construction of your regular expression, and the use of special characters:

  • In the test statement [[ "$File_name" =~ ^[[:alnum:]][[$_."#&']] ]], you use a character list [$_."#&'] with characters that are special to the shell: The $_ for example, will likely be interpreted as the last shell argument, and the double-quotes " will be interpreted by the shell as the beginning of a literal string, which ends in the next line with the first " of your echo command. This should throw a syntax error, beacuse the shell tries to interpret your output message as shell commends; it definitely does so when I try it. You should make sure to escape such characters to inhibit unwanted interpretation by the shell, as in \$_\"\#\&\'.
  • Also, you use double square brackets [[ ... ]] for a character list. However, this is syntactically undefined. What is defined is a character list [ ... ] consisting of only one character class, e.g. [:alnum:]. This kind of construct would indeed be written as [[:alnum:]], as you already did in the first part of your regular expression. You should therefore omit the "outer" pair of square brackets.
  • You have started your regular expression with the "start anchor" ^. I assume therefore that you want to allow filenames that start with a regular letter or number, but then may contain all special characters you mentioned. However, your regular expression allows only for filenames starting with one alphanumeric character and then requiring one of the special characters as second character. If you want to ensure that any number of these are allowed in addition to alphanumeric characters, you would instead write something like ^[[:alnum:]][[:alnum:]\$_.\"\#\&\']*$. The second part is then a character list [ ... ] containing the character class [:alnum:] and in addition the special characters $, _, ., ", #, & and ', zero or more times (*) until the end of the string ($). This last anchor character ensures that the entire filename consists only of the characters you allowed.

Your next point concerns that the ${now} variable is not resolved (i.e. "expanded" in the shell terminology).

  • As was already noted in several comments, parameter expansion does not happen inside single quotes ' ... '. If you use double quotes " ... " instead, the variable expansion will work.

  • You seem to be certain that you need single quotes at this point. It that is really so, there is little you can do; in that case, you may need to further explain why you need the single quotes (i.e. what you want to achieve, or whether further processing of the expression 'abc_${now}' including the quotes is desired later in the process).

AdminBee
  • 22,803