Executing multiline sed in php: escaping issues - php

I am trying to run sed to do a multiline search and replace with the following string
$test = "sed -n '1h;1!H;${;g;s/iname=\"".$name.".*item>/".trim(xml)."/g;p;}' ".$file;
exec($test,$cmdresult);
sed is choice since the string to be searched is over 10 mb.
During execution compiler issues a warning
PHP Parse error: syntax error, unexpected ';'
How do I go about solving this?

You need to escape the $ in ${}.
$test = "sed -n '1h;1!H;\${;g;s/iname=\"".$name.".*item>/".trim(xml)."/g;p;}' ".$file;
exec($test,$cmdresult);
In order to let humans read your code, though, you should really split the string up. Create it by concatenating other strings, sprintf or HEREDOC.

Probably the $ sign inside the $test variable makes PHP think that there is another variable that should be expanded.
Try escaping the $ character (\$), and have a look at the relevant PHP strings doc.

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.

Replacing "/\ characters with sed, from within php

I generate password from php (thru web page) using shell_exec / dd/ /dev/urandom.
I want to eliminate
"/\
characters from my generated password.
If I do a replacement in my sed line with
's/["/\]/!/g'
the script fails to execute. However I tested this from command line like
echo "this /is \"a \test" | sed -e 's/["/\]/!/g'
Then I get the right result : this !is !a !test
If I eliminate this replacement section from my sed line, php script does execute properly. What seems to be the issue? I thought characters within brackets [] is safe and does not need escaping.. is that the issue?
In PHP, if you use the command in a double quoted string literal, you need to escape the " with a single backslash, \", and the backslash inside the bracket expression must also be escaped.
In the end, this must look like
sed 's/[\"/\\]/!/g'

Replace string with special characters

I'm trying to replace the following string in a wordpress sql file:
http:\\/\\/firstdomain.com\\/qwerty\\/wp-content\\/uploads\\/2018\\/07\\/section-shape.png
to
https:\\/\\/seconddomain.com\\/wp-content\\/uploads\\/2019\\/06\\/section-shape.png
I tried the following command which obviously didn't work
sed -i "s#'http:\\/\\/firstdomain.com\\/qwerty\\/wp-content\\/uploads\\/2018\\/07\\/section-shape.png'#'https:\\/\\/seconddomain.com\\/wp-content\\/uploads\\/2019\\/06\\/section-shape.png'#g" database.sql
Someone please help to understand where I missed. Thank you very much.
You can't seriously apply a sed to a .db file because... well, it's database file not text (most likely sqlite by the way).
Instead, you should perform the string replacement with an (UPDATE) SQL query from the SQLite console (or whatever SQL client you have). Check this link for the replace method in SQLite for example.
Your first mistake is enclosing your script in double quotes instead of single, thereby inviting the shell to parse its contents before sed gets to see it and thus eating up one layer of backslashes.
If you have to deal with single quotes (which you shouldn't given your posted sample input but anyway...) never do this:
sed "s/foo'bar/stuff/"
do this instead:
sed 's/foo'\''bar/stuff/'
so the shell isn't interpreting every part of your script.
Beyond that - sed doesn't understand literal strings (see Is it possible to escape regex metacharacters reliably with sed), so instead just use a tool that does, e.g. awk:
awk '
BEGIN { old=ARGV[1]; new=ARGV[2]; ARGV[1]=ARGV[2]="" }
s=index($0,old) { $0 = substr($0,1,s-1) new substr($0,s+length(old)) }
1' \
'http:\\/\\/firstdomain.com\\/qwerty\\/wp-content\\/uploads\\/2018\\/07\\/section-shape.png' \
'https:\\/\\/seconddomain.com\\/wp-content\\/uploads\\/2019\\/06\\/section-shape.png' \
file
https:\\/\\/seconddomain.com\\/wp-content\\/uploads\\/2019\\/06\\/section-shape.png

sed regex cut string

I have about 200 php files that containing some iconv() functions,
something like this:
iconv('GB2312','UTF-8',$aRow[$aColumns[3]])
iconv('GB2312','UTF-8',$rs1['supplier']);
iconv('GB2312','UTF-8',$aRow[ $aColumns[$i] ]);
i don't know what could be the best way to remove iconv('GB2312','UTF-8', and final ) in batch mode without touching the variable.
this RegEx could match my case but i don't know how to use it with sed:
^(iconv\(\'GB2312\'\,\'UTF-8\'\,)+|(\))
And i am also not sure that sed is the right solution in this case
Anyone faced a similar problem before?
You can use this sed command:
sed -i "s/iconv('GB2312','UTF-8',\([^)]*\))\(.*\)/\1\2/" file
which will extract your php variable into \1. /2 is the remaining of the line (a ; in the example you posted)
Try this cut statement with the output.
cat file|cut -d, -f3|tr -d ');'
This might work for you (GNU sed):
sed 's/iconv('\''GB2312'\'','\''UTF-8'\'',\([^)]*\))/\1/g' file
Use an example string as a template, replacing ' by '\'' and the variable to be kept as any characters from after the second , which is not a closing ). This variable is enclosed in quoted (...) i.e. \(...\) which may be transfered to the RHS of the substitution command as a back reference.
Try this sed:
cat file | sed 's/iconv(.*,.*,\(.*\)).*/\1/g'
This will extract only the variable.
With grep
grep -o '$[^)]*' infile

Php and unix grep backslashing does not work

I have a fairly simple problem I just cannot seem to find a solution. I want to delete a line containing a certain string in all the files in a directory on my website. This string contains double quotes though. I have been trying to find a solution using backslashing but its does not work.
The string I want to replace is:session_register("c$key");
I'm using this php and unix code:
$command = "sed -i '/session_register(\"c$key\")/d;' ./*";
$output = shell_exec($command);
I want to delete this line because session_register is outdated.
It does not do anything but does not give me an error. What is the problem or how should I backslash?
Thanks a lot!
You need to double escape $ as well since $ is special regex symbol means end of input. Also use single quote instead of double for your $command string assignment.
Try this:
$command = 'sed -i.bak \'/session_register("c\\$key")/d;\' ./*';
$output = shell_exec($command);

Categories