I am quite familiar with sed on bash shell, so I do
cat $myfile | egrep $pattern | sed -e 's/$pattern/$replace/g'
a lot. Quite a few times, I find that I need to do similar kind of "string parsing" inside PHP.
So my question is simple, what is the equivalent of sed -e 's/$pattern/$replace/g' in PHP ?
I know preg_match , preg_replace , but I haven't used them / not at all familiar with them. I would really appreciate sample code in PHP. (converting say a $var = '_myString' to $newVar = 'getMyString' )
The preg_ functions uses the same regexp library that Perl does, so you should be at home. There's documentation of the syntax here.
For example:
sed -e 's/$pattern/$replace/g'
Would be something like:
$output = preg_replace("/".$pattern."/", $replace, $input);
The most common is to use / as delimiter, but you can use other characters, which can be useful if the pattern contains lots of slashes, as is the case with urls and xml tags. You may also find preg_quote useful.
Related
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
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
I'm trying to change to migrate my php code using ZF1/PEAR convention to namespaces.
So I want is to change
$locale_test = (new ACME_Common_Factory())->createLocale(ACME_Common_Enum_Civility::MR);
to
$locale_test = (new \ACME\Common\Factory())->createLocale(\ACME\Common\Enum\Civility::MR);
I've tried using the following sed program (which would work for lines containing only 1 class name)
sed -r '/ACME/{h;s/ACME_.*$//1;x;s/^.*(ACME.*)$/\\\1/;s/_/\\/g;x;G;s/\n//1}'
But it actually does little more than
sed -r '/ACME/s/_/\\/g'
I would prefer a solution using sed or awk (just for the sake of improving my cli skill) but any other solution will do.
Spaces as well as most special characters (but, crucially, not _) end a word, so I believe the word boundaries should serve well to identify class names. So, using GNU sed:
sed 's/\>/\n/g; :a s/\<\(ACME[^\n]*\)_\([^\n]*\)/\1\\\2/; ta; s/\<ACME/\\&/g; s/\n//g' filename
This works as follows:
s/\>/\n/g
puts newlines after closing word boundaries. We use this later to match (sort of) non-greedily. After this step, your line becomes
$locale_test
= (new
ACME_Common_Factory
())->createLocale
(ACME_Common_Enum_Civility
::MR
);
This leaves us with an easy way to identify names in the ACME namespace: \<ACME[^\n]*, and to identify names in the ACME namespace that contain an underscore: \<ACME[^\n]*_[^\n]*. We can use this to find underscores in ACME names and replace them one by one:
:a # jump label for looping
s/\<\(ACME[^\n]*\)_\([^\n]*\)/\1\\\2/ # Attempt replacement
ta # if it happened, go back to a.
After that, it's just
s/\<ACME/\\&/g
To put the \ in front, and
s/\n//g
To remove the newline markers we put there.
Mind you, I suspect that this would be easier in Perl.
This might work for you (GNU sed):
sed -r ':a;s/(ACME[a-zA-Z\\]*)_/\1\\/;ta;s/ACME/\\&/g' file
What about this ?
sed -r -e '/ACME_[^\(:]*/s/_/\\/g' -e 's/(ACME\\)/\\\1/g'
I've finally found an answer inspired by #Wintermute
sed -r ':a s/(ACME[^;:\(]*)_([^;:\(]+)/\1\\\2/g; ta' file
I have many fields in my smarty template files like this.
{$email} (this can be anything like -- {$description}, {$variable_name}
I want to replace it with {$email|escape:htmlall} or {$variable_name}
how can i do that in linux? I'm having difficulty writing regex in sed.
Try:
sed 's/{\(\$[^}\|]*\)}/{\1|escape:htmlall}/g'
As a test, use:
echo 'blabla {$email} blieblie {$name} bloebloe ${alreadydone|escape:htmlall}'|sed 's/{\(\$[^}\|]*\)}/{\1|escape:htmlall}/gi'
Things that this regexp does:
It replaces any string like {$} by {$|escape:htmlall}
It also makes sure that two consecutive fields (as in the example) are handled separately. This is done by demanding that in the no '}' may occur (this is done by the [^}\|]* part, which means: a series of zero or more characters which all may be anything but '}' and '|' (see below).
It ignores any tags that already were escaped (by ignoring any tag having a | within the curly braces).
Make a backup before and try this:
grep -rl "{$email}" yourdirectory | xargs sed -i 's/\{\$email\}/{$email|escape:htmlall}/g'
perl -ape 's/({\$\w+)(?!\|escape:htmlall)}/$1|escape:htmlall}/g' file
This is using the negative lookahead feature.
This will ignore variables that already have escape:htmlall.
How can I grep a pattern that can include spaces, commas etc using exec or system in PHP, and return one string separated by a comma each result. If needed, I can make use of awk or sed to separated by comma.
So for instance, if the pattern to search is: hello worl
then return:
$result = 'hello world, hello worlds, hello worldy';
Any ideas will be appreciated. Thanks
Check out escapeshellarg() and escapeshellcmd().
Edit:
Is this in just one file? If you're not searching across the system then just use the built-in functions, they'll be plenty fast.