简体   繁体   中英

Bad substitution Bash: how to write a heredoc to a dynamically created file (variable)?

I am about to generate a lot of surveys in php.

I'm using Bash to add some kind of automation with the cat command. So I use Bash to generate .php files.

To add a new survey, my Bash script counts the files in the survey directory with filecount='ls -l ${survey_dir}${survey_category} | wc -l' filecount='ls -l ${survey_dir}${survey_category} | wc -l' . I want to use filecount to generate the filename of the next survey. So if the survey_category directory has two files, the new filename will be 3.php .

Before starting the heredoc, I issue the following variables and commands:

filecount=$((filecount+1))
newfile="${wd}${catg}/${filecount}.php"
cat > ${newfile} <<-EOF
...
EOF

When I execute the script the cat command yields the error message 'Bad substitution'.

I tried to overcome this by quoting the <<-EOF : like <<-'EOF' , however I use a lot of variable substitutions in php, so this solution can't be implemented.

I checked if ls -l /bin/bash actually links to bash and not dash or another sh shell.

I checked if my 'shebang' is #!/bin/bash and not #!/bin/sh . Checked ok.

Furthermore I tried to use single and double quotes on the variable ${newfile} : to no avail.

Debug info #!/bin/bash -x :

: bad substitution
+ [[ 1: == \2\: ]]
+ [[ 1: == \3\: ]]
+ [[ 1: == \4\: ]]

My question is: how to write a heredoc to a dynamically created file?

Code that is causing the problem:

    echo -e "Your question please:"
    read -e rvraag
    rvraag="${rvraag//\"/\^}"
    salt=`date +"%s"`
    filecount=`ls -l ${wd}${catg} | wc -l`
    filecount=$((filecount+1))
    newfile="${wd}${catg}/${filecount}.php"
    cat > ${newfile} <<-EOF

    <?php
     session_start();
    \$st_code =\$_SESSION['studentnr'];
    \$cursuscode ="${catg}";
    \$rdir="/var/www/qqlq.org/www/gen_enq/";
    require_once \$rdir.'/inc/error_reporting.inc';
    require_once \$rdir.'/src/clsQuestionProgress.class.php';
    \$myQuestionProgress = new clsQuestionProgress();
    \$myQuestionProgress->fCreateQuestionProgress( \$st_code, \$cursuscode );
    require_once \$rdir.'/inc/header.inc';
    require_once \$rdir.'/src/clsWriteProgress.class.php';
    echo "<div class='container'><hr>
    Vraag ${catg} ${filecount}<h4> ${rvraag}</h4><br><br>
    <form name='qradio' action =".\$_SERVER['PHP_SELF']." method= 'POST'>
    <div class='radio'><label><input type='radio' name='${catg}${salt}'

    value='1'>${answ1}<label></div>
        <div class='radio'><label><input type='radio' name='${catg}${salt}' value='2'>${answ2}<label></div>
        <div class='radio'><label><input type='radio' name='${catg}${salt}' value='3'>${answ3}<label></div>
        <div class='radio'><label><input type='radio' name='${catg}${salt}' value='4'>${answ4}<label></div>
       <input type='submit' class='btn btn-warning' name='btnCancel${salt}' value='Go Back'>
       <input type='submit' class='btn btn-success' name='btn${catg}${salt}' value='Ok'>
    </form>
    <hr></div>";
    if (  \$_POST['${catg}${salt}'] == "${answok}" && isset( $_POST['btn${catg}${salt}'] ) ){
          \$myProgress = new clsWriteProgress();
          \$tablename = 'q'.\$st_code.\$cursuscode;
          \$myProgress->fSetProgress( \$tablename, \$_SESSION["leerjaar"],$st_code,\$cursuscode,"${rvraag}",1 );
          \$nextpage=${filecount)+1;
          echo '<script>location.replace("'.\${nextpage}.php.'");</script>';
    }//end if

     if (  \$_POST['${catg}${salt}'] !== "${answok}" && isset( \$_POST['btn${catg}${salt}'] ) ){

          \$tablename = 'q'.\$st_code.\$cursuscode;
          \$myProgress = new clsWriteProgress();
          \$myProgress->fSetProgress( \$tablename, \$_SESSION["leerjaar"],\$st_code,\$cursuscode,"${rvraag}",0 );
          \$nextpage=${filecount)+1;
          echo '<script>location.replace("'.${nextpage}.php.'");</script>';
    }//end if

    if ( isset( \$_POST['btnCancel${salt}'] ) ){
            echo '<script>location.replace("../../studyoverview.php" );</script>';

    }//end if
EOF

我相信Heredoc的语法是<<不是<<-

As pointed out in Benjamin W's comment, the problem was caused within the php code that should have been written to a file.

In my code I wrote $nextpage=${filecount)+1; Mark the parenthesis!

It should have been: $nextpage=${filecount}+1;

The strategy to analyse the 'Bad substitution' error, was to start with an empty bash script. After that I wrote the heredoc skeleton testing it line by line. When no error returned, I pasted the following line and so on until I reached the '$filecount}+1' expression.

Problem solved, thanks for your feedback!

@kzpm: Basing on code you provided this works for me:

!/bin/bash

wd="/tmp/workdir/"
catg="survey01"
mkdir -p ${wd}${catg}
filecount=`ls ${wd}${catg} | wc -l`
filecount=$((filecount+1))
newfile="${wd}${catg}/${filecount}.php"
echo "${newfile}"
cat > ${newfile} <<-EOF
<?php ..... ?>
EOF

Changes i made:
1. Backticks for ls (single quotes in your code and probably that was the case)
2. Moving setting catg value at the beginning (you were declaring it after filecount)

Just rewrite this as a PHP shell script, if you're working in an environment that you know has PHP installed. Seriously, some headaches just aren't worth your time. Bash is nice if you're looking for something quick and dirty, but as soon as you start throwing certain characters (chiefly dollar signs) into the mix, you're setting yourself up for a lot of debugging.

Details on using PHP from the command line:
http://www.php.net/cli

You can get user input at the command line using:

echo "Your question please: ";
$question = fgets(STDIN);

(Some people will no doubt chime in that Python or Perl are better bets, but since you're outputting PHP anyway it makes sense to stick with a single langauge.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM