sed regex cut string - php

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

Related

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

How to insert a string with double quotes in the first line of my csv file?

I am looking for a way to insert this:
"random1","random2"
in the first line of my csv file using sed.
Tried hard and only got this:
sed -i -e '1irandom1 random2\' filename
Output is just random1 and random2 without any double quotes - clearly.
Any good idea?
Have you tried
sed -i -e '1i"random","random2"\' filename
If you want the quotes (and the comma), you need to explicitly specify what is written, verbatim.
If you want double quotes, type double quotes:
sed -i~ -e '1s/^/"random1","random2"/' filename
i inserts a line, so I used substitution s, replacing ^, i.e. the beginning of the line, by the given string.
Maybe something like:
sed 's/^.*$/"random1","random2"/g' filename would work.

Replace a char within a pattern with sed

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

Replacing the value of input tag across multiple files

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.

Linux SED search replace multiple per line

I need to replace a whole bunch of PHP super globals in a clients website with a PHP function I made to clean the superglobals from xss attacks.
Here is what the original code might look like:
echo $_REQUEST['HELLO1'] . ' AND ' . $_REQUEST['HELLO2'];
I need it to look like this:
echo MYCLASS::myfunction($_REQUEST['HELLO1']) . ' AND ' . MYCLASS::myfunction($_REQUEST['HELLO2']);
The main issue, I need to do a search/replace on over 100 files! Yikes!
So my solution was this (in linux shell):
sudo sed -i 's/\$_REQUEST[.*\]/MYCLASS::myfunction(&)/g' *.php
This works great as-long-as only one instance of "$_REQUEST" occurs per line... However with multiple instances, it screws up and does this:
echo MYCLASS::myfunction($_REQUEST['HELLO1'] . ' AND ' . $_REQUEST['HELLO2']);
The problem is that .* is greedy and will find the longest possible match it can. To work around that use [^]]* instead so that you don't inadvertently grab up an extra set of square brackets.
sudo sed -i 's/\$_REQUEST\[[^]]*\]/MYCLASS::myfunction(&)/g' *.php
In other regex dialects you could also write .*? to make the wildcard non-greedy, but that doesn't appear to work in sed (at least not in my version, not even with sed -r).
Try this sed command:
sed -i.bak 's/\$_REQUEST\[\([^]]*\)\]/MYCLASS::myfunction(\1)/g' *.php
or in perl:
perl -pe 's/\$_REQUEST\[([^]]*)\]/MYCLASS::myfunction(\1)/g' file.php
In Perl, the following script will work where you pass the script the name of the file you are interested in
lets say the script is t.pl and your file is file.php
to output back to file.php
perl t.pl file.php > file.php
to output to another file so you don't overwrite your original
perl t.pl file.php > another_file.php
#!/usr/bin/perl
$FILE_NAME = $ARGV[0];
open (FILE_NAME) or die ("Could not open FILE_NAME information file: $FILE_NAME \n");
#file_contents = <FILE_NAME>;
close (FILE_NAME);
foreach $line (#file_contents) {
chomp($line);
$line =~ s/\$_REQUEST\[.*?\]/MYCLASS\:\:myfunction\($&\)/g;
print $line." \n";
}
exit;
sed 's/\$_REQUEST\[[^]]*\]/MYCLASS::myfunction(&)/g'
This should do it:
sed -i "s/\$_REQUEST\[\([^\x5d]*\)\]/MYCLASS::myfunction(\1)/g" *.php
I had a lot of trouble matching ], so I've punted with \x5d.

Categories