How can execute php scripts in bash? - php

I need parse uri in shell scripts. So, I tried to use php in bash as below.
#!/bin/sh
uri="http://www.google.com?key=value
key="host"
value=$(php -r "$parse = parse_url('$uri'); echo $parse['$key']")
It has showing the following error.
PHP Parse error: syntax error, unexpected '=' in Command line code on line 1
Some body can help how to use embedded php in bash ?

A cheap way of debugging this is to use echo to see what you're passing in to php:
echo "$parse = parse_url('$uri'); echo $parse['$key']"
shows
= parse_url('http://www.google.com?key=value'); echo ['host']
You're already using $uri to mean "the value of the shell variable uri", so it's not surprising that $parse is also considered a shell variable and expanded to its value (unset, nothing).
Use \$ when you want a literal dollar sign in your double quoted string:
value=$(php -r "\$parse = parse_url('$uri'); echo \$parse['$key']")

You can use it easily, but you must be careful because of escaping in bash.
I recommend to use single quotes (you do not need to escape anything) and exit from the quotes when you want to do something special. Your example:
php -r '$parse=parse_url("'$url'"); echo $parse["'$part'"];'
Note that
you do not need to escapes $parse
you need to exit from single quotes when inserting bash variable: '$url'
you cannot use single quotes in the single quotes! do use double quotes " instead.
Update:
Just for the clarification - parse error happened because $parse was interpreted as bash variable (empty string) so the php command incorrectly started with =.

Related

How to resolve unexpected token error with grep, regex, and PHP?

I know REGEX well enough but am stuck on this one. I am using PHP 5.4 to shell_exec() a grep statement with REGEX inside it to capture the SKU in a text file. In php I don't see an error but the grep doesn't work.
The goal is to capture the SKU in this text:
{'Product_Product_SKU': 'DOP36M94DPM'},
PHP Code:
$cmdSKU1 = 'grep -Po \'(?<=\{\'Product_Product_SKU\':\s{15}\').+?(?=\'\}\,)\' '.$FileName;
$chkSKU1 = trim(shell_exec($cmdSKU1));
Furthermore, when I look at the $cmdSKU1 variable in the debugger tool of the IDE I am using it's value is this as one line:
grep -Po '(?<=\{'Product_Product_SKU':\s{15}').+?(?='\}\,)' /opt/web/default/RetailerParsing/RetailerDownload/MDD30TMSTH__20220113091043.htm
Furthermore some more, when I paste it into the Ubuntu console it gives me the error:
-bash: syntax eror near unexpected token `)'
Even if I go back and escape the exposed single quotes. Infact, I escaped everything [^A-Za-z0-9] just to make sure! No beans.
Lastly, if I try to double escape the single quotes within the REGEX in the PHP IDE I get a red squiggly underline error under the words Produce_Product_SKU.
You're not escaping the shell command correctly. Instead of doing it manually, you should use ​escapeshellarg:
$cmdSKU1 = join(" ", array_map( 'escapeshellarg', array(
​"grep",
​"-Po",
​"(?<={'Product_Product_SKU':\s{15}').+?(?='},)",
​$FileName
)));
$chkSKU1 = trim(shell_exec($cmdSKU1));
That said, why not directly use preg_match and save a call to a non POSIX external command?
$string = "{'Product_Product_SKU': 'DOP36M94DPM'},";
preg_match("/{'Product_Product_SKU':\s{15}'([^']+)'}/", $string, $matches);
var_dump($matches[1]);
string(11) "DOP36M94DPM"
Of course you'll have to read the file inside php, but it may be worth the extra code.
You don't need regex at all here, and certainly not a shell_exec. Just split on ' and take the 4th (0-indexed) value out of the resulting array:
$str = "{'Product_Product_SKU': 'DOP36M94DPM'},";
$sku = explode("'", $str)[3];
var_dump($sku);
Yields:
string(11) "DOP36M94DPM"
Also note PHP 5.4 was end-of-lifed over 6 years ago. You really should update.

How insert an XML in a command line [duplicate]

I got one error while passing the arguments to outlook_DataParsing.sh:
$ sh outlook_DataParsing.sh delete node doc('/opt/ws40/contacts.xml')//Directory/Contacts/Contact[#id='22222']
and I am reading all the arguments as:
str=$#
The error is following:
-bash: syntax error near unexpected token `('
Can anybody help me?
There are a number of "special" characters in a shell command, including $()[]
Most of these can simply be passed by enclosing the parameter in double quotes
foo "(hello)[]"
This however will not fix the $ sign, as it is intended for variables. You can instead use single quotes to pass a $ sign
foo '$im_not_a_variable'
If all else fails, ANY character can be escaped with a backslash \ including a space (no quotes needed)
foo \(hello\)\[\]\ \$im_not_a_variable

awk command to find average of a column from a file

I have written an awk command to read from a log file and get the average of a specific column.
The command is :
awk '{sum += $NF} END {print sum/NR}' /serach_grater500ms_test.txt
Everything is working fine on terminal but when I try to execute this command in php script as follow :
$no_of_request=exec("awk '{sum += $NF} END {print sum/NR}' /serach_grater500ms_test.txt");
print_r($no_of_request);
It throw me a syntax error
PHP Notice: Undefined variable: NF in /home/javed/Downloads/read_log.php on line 11
awk: line 1: syntax error at or near }
How can I solve it ?
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.
exec('awk \'{sum += $NF} END {print sum/NR}\' /serach_grater500ms_test.txt');
In your example the php string is between double-quote ". The character ' inside has no special meaning, you dont need to escape it. On the other hand the $ (like in sum += $NF) is interpreted, so the php replaces $NF with its value (empty!).
With Inian's answer the php string is between single-quote '. So the php does not look for variable inside ($NF is protected); but you have to escape further \' inside.
You can also have it work with the double-quote of your example; but you escape only the \$ of $NF :
$no_of_request=exec("awk '{sum += \$NF} END {print sum/NR}' filee");

PHP SSH Lib, echoing to a file

I'm trying to create a PHP script that creates a file on a remote linux server through ssh, and echos the file contents into it.
However, I cannot figure out how to correctly and safely encode/escape the file contents, so that the contents don't get interpreted as commands.
I'm using phpseclib from here.
I've tried something like
echo $ssh->exec('sudo echo "' . escapeshellarg($newConfig) . '" > /etc/nginx/nginx.conf') . "\n";
but without success.
Thanks,
Steve
What about escapeshellcmd? Quoting the description of that vs escapeshellarg:
escapeshellarg() adds single quotes around a string and quotes/escapes
any existing single quotes allowing you to pass a string directly to a
shell function and having it be treated as a single safe argument.
...and...
escapeshellcmd() escapes any characters in a string that might be used
to trick a shell command into executing arbitrary commands. This
function should be used to make sure that any data coming from user
input is escaped before this data is passed to the exec() or system()
functions, or to the backtick operator.
Following characters are preceded by a backslash: #&;`|*?~<>^()[]{}$\,
\x0A and \xFF. ' and " are escaped only if they are not paired. In
Windows, all these characters plus % are replaced by a space instead.
I was going about this all wrong, I should have used Net_SFTP instead of NET_SSH for this sort of thing.

PHP exec() with double quote argument

I've been having trouble running a command using PHP's exec() function on Windows. Per a comment on PHP's site on exec():
In Windows, exec() issues an internal call to "cmd /c your_command".
My command looks like:
"path\to\program.exe" -flag1 attribute1 -flag2 attribute2 -flag3 "attribute3 attribute4"
Under regular execution of this command in my local command prompt, without the /c flag, the command runs fine. However, with the introduction of the /c flag, command prompt tells me that "The system cannot find the path specified."
I think the command prompt is interpreting the double-quoted argument as a path to another file, but that's the furthest I've gotten with this problem.
Does anybody have any ideas on how to get past this? Thanks!
I also encountered this issue, and the cause of it is, indeed, the internal use of "cmd /c" as described in your own answer.
I have done some investigation, and have found that this was resolved in PHP 5.3, which is why some commenters were unable to reproduce it.
It was fixed in the following commit:
https://github.com/php/php-src/commit/19322fc782af429938da8d3b421c0807cf1b848a#diff-15f2d3ef68f383a87cce668765721041R221
For anyone who still needs to support PHP 5.2, it is fairly easy to replicate the fix in your own code. Instead of:
$cmd = "...any shell command, maybe with multiple quotes...";
exec($cmd);
use
function safe_exec($cmd, &$output = null, &$result_code = null) {
if (strtoupper(substr(php_uname('s'), 0, 3)) == "WIN"
&& version_compare(PHP_VERSION, "5.3", "<"))
{
$cmd = '"' . $cmd . '"';
}
return exec($cmd, $output, $result_code);
}
$cmd = "...any shell command, maybe with multiple quotes...";
safe_exec($cmd);
This replicates the behaviour of PHP 5.3 and above, in the same way as in the above-linked commit.
Note that this applies to all shell commands, not just exec() as used in my example.
I've figured out the answer by myself...
After perusing cmd.exe's /? and trying to decipher that, I've noticed one important section:
If all of the following conditions are met, then quote characters on the command line are preserved:
No /S switch (Strip quotes)
Exactly two quote characters
No special characters between the two quote characters, where special is one of: & < >( ) # ^ |
There are one or more whitespace characters between the the two quote characters
The string between the two quote characters is the name of an executable file.
Otherwise, old behavior is to see if the first character is a quote character and if so, strip the leading character and remove the last quote character on the command line, preserving any text after the last quote character. To negate this behaviour use a double set of quotes "" at the start and end of the command line.
It seems as though if there more than one pair of quotes at any time, quotation marks will be stripped from the second pair of quotes and on.
A relevant question: How do I deal with quote characters when using cmd.exe but not completely relevant, since PHP will not allow you to modify its exec() command by putting an /S flag on its call (which would definitely be a lot easier).
I've managed to work around this problem by directly changing directories with chdir() to the folder where the .exe is located, then chdir()'ing back to my original working directory. It's an extremely hacky solution, given the case that I'm lucky that I only have one set of arguments using double quotes. If anybody were to have multiple arguments using double quotes, I wouldn't know how to solve that...
Just a guess (I am not familiar with PHP on windows): maybe escape the quotes as " becoming ""?
"path\to\program.exe" -flag1 attribute1 -flag2 attribute2 -flag3 ""attribute3 attribute4""
Whatever the solution is, make sure that when there's some form of user-input that gets passed to this command as arguments that you use escapeshellarg and/or escapeshellcmd.
I hope it will help
escapeshellarg() — Escape a string to be used as a shell argument
escapeshellcmd() — Escape shell metacharacters

Categories