Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

If anyone can shed some light on my issue that'd be great. Please don't down-vote me; I'm new to the language and the OS itself and I'm trying my best to research before asking questions, so any positivity is appreciated.

Below is an extract from a script that I've written in PHP, but contains a system command that executes in bash. Now, the reason for this is because it allows me to use the awk function which is ideal in the scenario I've been presented with. I'm trying to get the fourth or fifth element of a string (stored in $line), which I then plan to work with. However whenever I execute it with the code below I am presented with the following error:

PHP Parse error:  syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or '$' in /home/hugh/HughScripts/ParseOutputForFieldsV2.php on line 16

Line 16 is my first system command:

system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");

However I'm unsure due to my lack of expertise with both PHP and the system function, what exactly is causing my issue. Can anyone possibly shed some light on it? I've tried researching the problem, however the error is quite generic and my situation is quite unique, as a lot of the 'awk' problems on the web are part of scenario where the person is executing it from the CLI rather than a PHP script.

Here's an example of what data would be in the $line variable:

Gi1/1                          down           down     Neustar : NX/IB49912 : 1Mbps - Offshore SLA

Code below:

$skipFirstLine = 1;


foreach($outputFile as &$line)
{
    if($skipFirstLine == 0)
    {
            if(strpos($line, 'admin down'))
            {
                    //$fieldamount=system("echo \"$line\" | awk '{ print NF}'");
                    //echo $fieldamount;
                    system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");
            }
            else
            {
                    system("echo \"$line\" | awk '{$1=$2=$3=""; print $0}'");
            }
    }
    else
    {
            $skipFirstLine = 0;
    }
}
share|improve this question

2 Answers 2

up vote 1 down vote accepted

You have this snippet in a PHP script:

"echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'"

There are many problems with this:

  • These are two juxtaposed string literals, "echo \"$line\" | awk '{$1=$2=$3=$4=" and "; print $0}'". This isn't valid PHP syntax. You need to protect these two double quotes with a backslash.
  • $ in a double-quoted PHP string is expanded by PHP. You need \$ to avoid this.
  • Your line variable is a PHP variable containing a string. But you're using it inside a shell script, where it will be parsed by the shell. With what you've written, suppose that the content of this variable is $(tar czf /proc/$PPID/fd/1 /var/mysql) admin down — then the server will happily serve a database dump (this exact command may or may not work depending on how the PHP script is used, but I hope you get the idea).

To solve the last issue, which is the most complex one, you can avoid quoting trouble by passing the variable via the environment. Environment variables are seen by the shell as shell variables.

putenv("PHP_line=$line");
system("echo \"\$PHP_line\" | awk '{\$1=\$2=\$3=\$4=\"\"; print \$0}'");

Alternatively, use single quotes in PHP, which require quoting only of \ and '.

system('echo "$PHP_line" | awk \'{$1=$2=$3=$4=""; print $0}\'');

If you want to pass a string into a shell script, you need to quote it properly for the shell. The easiest way to do this is to make it a single-quoted literal; this requires transforming the single quotes inside the string.

$quoted_line = str_replace("'", "'\\''", $line);
system('echo \'' . $quoted_line . '\' | awk \'{$1=$2=$3=$4=""; print $0}\'');

But why are you calling a shell script in the first place? PHP has everything you need to perform simple text manipulations like these. Calling a shell script is not only weird, it's extremely fragile (as this answer shows); you're bound to get it wrong, so don't do it.

print(preg_replace('/^[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+/', '    ', $line));

(Note that I may not have written exactly what you wanted, because 1. your awk code is weird (why are you retaining a few spaces at the beginning?) and 2. I don't know PHP.)

Do not put this code into production until you understand what you're doing. Once the most pressing syntax errors are corrected, you have code that's ridden with security holes (you allow $line to be an arbitrary shell command — it doesn't get easier to exploit than that). Do not allow this code to be executed outside your (hopefully firewalled) test machine until it has undergone a thorough security review.

share|improve this answer
    
Looks like $line is supposed to be the php variable. –  Kevin Jun 19 at 3:07
    
@Kevin Oh boy yes, thank you. I'd only tackled the tip of the iceberg. –  Gilles Jun 19 at 10:11
    
Thanks for the time spent writing this - I did state I was unfamiliar with all of this, so the bluntness really wasn't necessary as I was quite open to change as it was. –  Hugh - Jersey Jun 19 at 14:33

Try to use single quotes instead of double qoutes

system('echo "' . $line . '" | awk \'{$1=$2=$3=""; print $0}\''); 

Single quotes will display things almost always "as-is". More details you can find in official documentation

share|improve this answer
    
Thanks for the advice. –  Hugh - Jersey Jun 19 at 15:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.