How to parse strings - detailed explanation and information on syntax - php

I would like to parse a sting of data in a shell script with a simple 1 line expression. But I do not know how or where to find any information describing how it is done. All the examples I can find just looks like an illegal math equations, and I can not find any documentation describing how it works.
First, what exactly is this form of parsing called so I know what I am talking about and what to search for. Secondly, where can I find what it all means so I can learn how to use it correctly and not just copy some one else's work with little understanding of how it works.
/\.(\w+)/*.[0-9]/'s/" /"\n/g;s/=/\n/gp
I recall learning about this in perl a couple decades ago, but have long since forgotten what it all means. I have spent days searching for information on what this all means. All I can find are specific examples with no explanations of what it is technically called and how it works!
I want to separate each field then extract the key name and numerical data in a shell script. I realize some forms of parsing are done differently in shell scripts as opposed to php or perl scripts. But I need to learn the parsing syntax used to filter out the specific data sets that I could use in both, shell and php.
Currently I need to parse a single line of data from a file in a shell script for a set of conditionals required by other support scripts.
#!/bin/sh
Line=`cat ./dump.txt`
#Line = "V:12.46 A:3.427 AV:6.08 D:57.32 S:LOAD CT:45.00 P:42.71 AH:2016.80"
# for each field parse data ("/[A-Z]:[0-9]/}" < $Line)
# $val[$1] = $2
# $val["V"] = "12.46"
# $val["AV"] = "6.08"
if $val["V"] < 11.4
then
~/controls/stop.sh
else
~/controls/start.sh
fi
if $val["AV"] > 10.7
then
echo $val["AV"] > ./source.txt
else
echo "DOWN" > ./source.txt
fi
I need to identify and separate the difference between "V:" and "AV:".
In php I can use foreach & explode into an array. But I am tired of writing half a page of code for some thing that can be done in a single line. I need to learn a simpler and more efficient way to parse data from a string and extract the data in to a usable variable.
$Line = file_get_contents("./dump.txt");
$field = explode (' ' , $Line);
foreach($field as $arg)
{
$val = explode (':' , $arg);
$data[$val[0]] = $val[1];
}
# $data["V"] = "12.46"
# $data["AV"] = "6.08"
A quick shell example is much appreciated, but I really need to know "HOW TO" do this my self. Please give me some links or search criteria to find the definitions and syntax to these parsing expressions.
Thank you in advance for your help.

The parsing patterns you're talking about are commonly referred to as regular expressions or regex.
For php you can find a lot of helpful information from http://au1.php.net/manual/en/book.pcre.php
Regex is quite hard especially for complex expressions so I usually google search for an online regex expression tester. Preferably one which highlights whats being matched. Javascript ones are especially good as the results are instant and the regex syntax is the same for PHP.

Special thanks to James T for leading me in the right direction.
After reading through the regular expressions I have figured out the search pattern I need. Also included is a brief script to test the output. Taking into account that BASH can not use decimal numbers we need to convert it to a whole number. The decimal intigers is always fixed at 2 or 3 places so conversion is easy, just drop the decimal. Also the order in which the fields are recorded remains constant so the order in which they are read will remain the same.
The regular expression that fits the search for each of the first 4 fields is:
\w+:([0-9]+)\.([0-9]+)\s
( ) = the items to search/parse; using 2 searches for each data set "V:12.46"
\w = for the word search and the " + " means any 1 or more letters
: = for the delimiter
( -search set 1:
[0-9] = search any numbers and the " + " means any 1 or more digits
) -end search set 1
\. = for the decimal point in the data
( -search set 2:
[0-9] = search any numbers and the " + " means any 1 or more ( second set after the decimal)
) -end search set 2
\s = white space (blank space)
Now duplicate the search 3 times for the first 3 fields, giving me 6 variables.
\w+:([0-9]+)\.([0-9]+)\s\w+:([0-9]+)\.([0-9]+)\s\w+:([0-9]+)\.([0-9]+)\s
And here is a simple script to test the output:
#!/bin/bash
Line="V:13.53 A:7.990 AV:13.65 D:100.00 S:BulkCharge CT:35.00 P:108.11 AH:2116.20"
regex="\w+:([0-9]+)\.([0-9]+)\s\w+:([0-9]+)\.([0-9]+)\s\w+:([0-9]+)\.([0-9]+)\s"
if [[ $Line =~ $regex ]]; then
echo "match found in $Line"
i=1
n=${#BASH_REMATCH[*]}
while [[ $i -lt $n ]]
do
echo " capture[$i]: ${BASH_REMATCH[$i]}"
let i++
done
Volt=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
Amp=${BASH_REMATCH[3]}${BASH_REMATCH[4]}
AVG=${BASH_REMATCH[5]}${BASH_REMATCH[6]}
else
echo "$Line does not match"
fi
if [ $Volt -gt 1200 ]
then
echo "Voltage is $Volt"
fi
resulting with an output of:
match found in V:13.53 A:7.990 AV:13.65 D:100.00 S:BulkCharge CT:35.00 P:108.11 AH:2116.20
capture[1]: 13
capture[2]: 53
capture[3]: 7
capture[4]: 990
capture[5]: 13
capture[6]: 65
Voltage is 1353

Related

Combine 2 CSV files based on a match within a column disregarding the header row

I have been scouring the ole interweb for this solution but have not found anything successful. I have a CSV output from one script that has data presented in a specific way and i need to match that and merge with another file. Added bonus if i can round up to a simple 2 x decimal points.
File 1: dataset1.csv (using column 1 as a primary key or what i want to search the other file for.)
5033db62b38f86605f0baeccae5e6cbc,20.875,20.625,41.5
5033d9951846c1841437b437f5a97f0a,3.3529411764705882,12.4117647058823529,13.7647058823529412
50335ab3ab5411f88b77900736338bc6,6.625,1.0625,3
5033db62b38f86605f0baeccae5e6cbc,2.9375,1,1.4375
File 2: dataset2.csv (if column 2 matches column 1 of file join column 1 from file 2 replacing the data in column 1 of file 1.)
"dc2","5033db62b38f86605f0baeccae5e6cbc"
"dc1","5033d9951846c1841437b437f5a97f0a"
Desired results:
File 1 (or new file3):
dc1,3.35,12.41,13.76
dc2,20.875,20.625,41.5
Just to demonstrate that I have been trying to find a way, and not just randomly asking a question hoping someone else would solve my problem.
I have found a number of resources that say to use join.
join -o 1.1,1.2,1.3,1.4,2.3 file 1 file 2 etc. I have tested this a number of different ways. I read on a number of posts that the results need to be sorted - with that long of a string its a little hard. Not to mention file 1 may have 30 to 40 entries but file2 may only have 10. I just need a name associated with the long string.
I started looking at grep - but then I will need a forEach loop to cycle through all the results and there has to be an easier way.
I have also looked at AWK - now this is a fun one trying to figure out exactly how to make this work.
awk 'FNR==NR {a[$2]; next} $2 in a' file.csv testfile2.csv
Yeah.... tried many ways to get this to compare as this seems to be the general idea... but still haven't got it to work. I would like this to be some type of shell script for linux to be very simple and something i can call from a php page and have it run. Like if user hits refresh it churns through it and digests the data.
Any help would be greatly appreciated!
Thank you.
j.
You can use a combination of sort and gnu awk:
mergef.awk:
BEGIN { FS= "[ ,\"]+"; }
FNR == NR { if ( !($1 in vals) ) vals [ $1 ] = sprintf("%.2f,%.2f,%.2f", $2, $3,$4) ;}
FNR != NR { print $2 "," vals[ $3 ]; }
Say your files are f1.csv and f2.csv then use this command:
awk -f mergef.awk f1.csv f2.csv | sort
the first line in the script deals with the quotes present in the second file (because of this setting there is an empty field $1 for the second file)
the second line reads in the first file. The if takes care that only the first occurence of a key is used.
the last line prints the new keys from the second file along the stored values from the first file, retrieved via the old keys
FNR == NR is true for the first file
Using python and the pandas library:
import pandas as pd
# Read in the csv files.
df1 = pd.read_csv(dataset1.csv, header=None, index_col=0)
df2 = pd.read_csv(dataset2.csv, header=None, index_col=1)
# Round values in the first file to two decimal places.
df1 = df1.round(2)
# Merge the two files.
df3 = pd.merge(df2, df1, how='inner', left_index=True, right_index=True)
# Write the output.
df3.to_csv(output.csv, index=False, header=False)
except formatting the numbers this does the job
$ join -t, -1 1 -2 2 -o2.1,1.2,1.3,1.4 <(sort file1) <(tr -d '"' <file2 | sort -t, -k2)
dc1,3.3529411764705882,12.4117647058823529,13.7647058823529412
dc2,2.9375,1,1.4375
dc2,20.875,20.625,41.5
note that there two matches for dc2.
Bonus: for required formatting pipe the output of the previous script to
$ ... | tr ',' ' ' | xargs printf "%s,%.2f,%.2f,%.2f\n"
dc1,3.35,12.41,13.76
dc2,2.94,1.00,1.44
dc2,20.88,20.62,41.50
but then, perhaps awk is a better alternative. This is to show that no programming is required if you can utilize existing unix toolset.
Here is a solution with PHP:
foreach (file("dataset1.csv") as $line_no => $csv) {
if (!$line_no) continue; // in case you have a header on first line
$fields = str_getcsv($csv);
$key = array_shift($fields);
$data1[$key] = array_map(function ($v) { return number_format($v, 2); }, $fields);
};
foreach (file("dataset2.csv") as $csv) {
$fields = str_getcsv($csv);
if (!isset($data1[$fields[1]])) continue;
$data2[$fields[0]] = array_merge(array($fields[0]), $data1[$fields[1]]);
};
ksort($data2);
$csv = implode("\n", array_map(function ($v) {
return implode(',', $v);
}, $data2));
file_put_contents("dataset3.csv", $csv);
NB: As you mentioned that the first file will be using column 1 as a primary key, a duplicate key value should not occur. If it does, the last occurrence will prevail.

Getting different output for same PHP code

(Can't paste the exact question as the contest is over and I am unable to access the question. Sorry.)
Hello, recently I took part in a programming contest (PHP). I tested the code on my PC and got the desired output but when I checked my code on the contest website and ideone, I got wrong output. This is the 2nd time the same thing has happened. Same PHP code but different output.
It is taking input from command line. The purpose is to bring substrings that contact the characters 'A','B','C','a','b','c'.
For example: Consider the string 'AaBbCc' as CLI input.
Substrings: A,a,B,b,C,c,Aa,AaB,AaBb,AaBbC,AaBbCc,aB,aBb,aBbC,aBbCc,Bb,BbC,BbCc,bC,bCc,Cc.
Total substrings: 21 which is the correct output.
My machine:
Windows 7 64 Bit
PHP 5.3.13 (Wamp Server)
Following is the code:
<?php
$stdin = fopen('php://stdin', 'r');
while(true) {
$t = fread($stdin,3);
$t = trim($t);
$t = (int)$t;
while($t--) {
$sLen=0;
$subStringsNum=0;
$searchString="";
$searchString = fread($stdin,20);
$sLen=strlen($searchString);
$sLen=strlen(trim($searchString));
for($i=0;$i<$sLen;$i++) {
for($j=$i;$j<$sLen;$j++) {
if(preg_match("/^[A-C]+$/i",substr($searchString,$i,$sLen-$j))) {$subStringsNum++;}
}
}
echo $subStringsNum."\n";
}
die;
}
?>
Input:
2
AaBbCc
XxYyZz
Correct Output (My PC):
21
0
Ideone/Contest Website Output:
20
0
You have to keep in mind that your code is also processing the newline symbols.
On Windows systems, newline is composed by two characters, which escaped representation is \r\n.
On UNIX systems including Linux, only \n is used, and on MAC they use \r instead.
Since you are relying on the standard output, it will be susceptible to those architecture differences, and even if it was a file you are enforcing the architecture standard by using the flag "r" when creating the file handle instead of "rb", explicitly declaring you don't want to read the file in binary safe mode.
You can see in in this Ideone.com version of your code how the PHP script there will give the expected output when you enforce the newline symbols used by your home system, while in this other version using UNIX newlines it gives the "wrong" output.
I suppose you should be using fgets() to read each string separetely instead of fread() and then trim() them to remove those characters before processing.
I tried to analyse this code and that's what I know:
It seems there are no problems with input strings. If there were any it would be impossible to return result 20
I don't see any problem with loops, I usually use pre-incrementation but it shouldn't affect result at all
There are only 2 possibilities for me that cause unexpected result:
One of the loops iteration isn't executed - it could be only the last one inner loop (when $i == 5 and then $j == 5 because this loop is run just once) so it will match difference between 21 and 20.
preg_match won't match this string in one of occurrences (there are 21 checks of preg_match and one of them - possible the last one doesn't match).
If I had to choose I would go for the 1st possible cause. If I were you I would contact concepts author and ask them about version and possibility to test other codes. In this case the most important is how many times preg_match() is launched at all - 20 or 21 (using simple echo or extra counter would tell us that) and what are the strings that preg_match() checks. Only this way you can find out why this code doesn't work in my opinion.
It would be nice if you could put here any info when you find out something more.
PS. Of course I also get result 21 so it's hard to say what could be wrong

Upgrade to PHP 5.4.29 (from 5.3?) broke my regex

My host just upgrade PHP the 5.4.29 from one of the 5.3 versions, I believe. This broke a very important regular expression that I use in a frequently used program.
I want to match variations on the following (each line is a separate example:
1 / AGGRAVATED ASSAULT Withdrawn 18 § 2702
1 / Simple Assault Guilty Plea 18 § 2701 §§ A
1 / Criminal Mischief Judgment of Acquittal 18 § 3304-12
This is my regex. It has worked for the last 2 years without fail:
/\d\s+\/\s+(.+)\s{12,}(\w.+?)(?=\s\s)\s{12,}(\w{0,2})\s+(\w{1,2}\s?\247\s?\d+(\-|\247|\w+)*)/
I use it as follows:
if (preg_match(self::$chargesSearch2, $line, $matches))
My expectation is that
matches[1] = the charge (Aggravated assault, etc...)
matches[2] = the grading (which often doesn't appear and isn't on any of these examples) matches[3] = the disposition (Withdrawn, etc...)
matches[4] = the code section (18 § 2702)
For some reason it doesn't work now--it doesn't match the lines in question. Does anyone see the error?
While I cannot answer the question of why it doesn't work any more, I can tell you that regex is not the right tool for this job. It's kind of like using a flat-headed screwdriver to drive cross-headed screws. Sure, it'll work, but it's easier to use the right tool.
In this case, you should make some kind of basic parser.
$line = "1 / AGGRAVATED ASSAULT ...";
list($count, $rest) = explode("/", $line, 2);
$count = intval(trim($count));
list($crime, $verdict, $details) = explode(" ",$rest);
$crime = trim($crime);
$verdict = trim($verdict);
$details = trim($details);
// I don't know what the significance of the $details are.
// But using the above you should be able to figure out how to parse it :)

Format MySQL code inside PHP string

Is there any program IDE or not that can format MySQL code inside PHP string e.g.
I use PHPStorm IDE and it cannot do it.
It does that for PHP and MYSQL but not for MYSQL inside php string. I am ready to use new IDE because now i have to manually format hundreds of database requests that are one line and not readable. Only criteria for my choice is that ide can do that automatically.
<?php
...
$request1 = "select * from tbl_admin where admin_id= {$_SESSION['admin_id']} and active= 1 order By admin_id Asc";
...
?>
should become
<?php
...
$request1 = "SELECT *
FROM tbl_admin
WHERE admin_id = {$_SESSION['admin_id']}
AND active = 1
ORDER BY admin_id ASC";
...
?>
The best way to do this in my opinion is to use Regular Expressions or SED/AWK to format everything, it gives us the bonus of replacement maps on the fly. The chance that you might have code errors though is high, so it's kind of tough.
let me work on it a bit and I can see if I can come up with a good
solution. Is it guaranteed that you are encapsulating all SQL in
double quotes?
EDIT
Try this
cd {{directory}} && find . -type f -print0 |
xargs -0 perl -i.bak -pe 's/select/SELECT/g ; s/from/\n\tFROM/g ; s/where/\n\t\tWHERE/g ; s/and/\n\t\tAND/g ; s/order by/\n\t\tORDER BY/g ; s/asc/ASC/g ; s/desc/DESC/g ;'
Here's an example
$ printf '"select * from whatever where this = that and active = 1 order by something asc";\n' |
> perl -pe 's/select/SELECT/g ; s/from/\n\tFROM/g ; s/where/\n\t\tWHERE/g ; s/and/\n\t\tAND/g ; s/order by/\n\t\tORDER BY/g ; s/asc/ASC/g ; s/desc/DESC/g ;'
"SELECT *
FROM whatever
WHERE this = that
AND active = 1
ORDER BY something ASC";
Is it pretty? no, not at all, does it work.... Yeup.
I'll try creating a filter file and maybe a little bash program or something as i get time to run this hot mess.
EDIT
Here's some revised code, looks prettier (sorta)
printf '$request1 = "select * from whatever where this = that and active = 1 order by something asc";\n' |
perl -pe 's/select/SELECT/gi ; s/from/\n FROM/gi ; s/where/\n WHERE/gi ; s/and/\n AND/gi ; s/order by/\n ORDER BY/gi ; s/asc/ASC/gi ; s/desc/DESC/gi ;' |
awk 'NR == 1 {pad = length($0)/2; print} NR > 1 {gsub(/\r/,""); printf "%*s%s\n", pad, " ", $0}'
__OUTPUTS__
$request1 = "SELECT *
FROM whatever
WHERE this = that
AND active = 1
ORDER BY something ASC";
As fas as I know PhpStorm can do it, if you use the heredoc syntax
$request1 = <<<SQL
SELECT *
FROM tbl_admin
WHERE admin_id = {$_SESSION['admin_id']}
AND active = 1
ORDER BY admin_id ASC
SQL;
The answer is NO.
As an alternative solution, I can suggest copying the text (ALL THE PHP CODE in the *.php file) into the query editor of Heidisql, clicking Re-Format and copying back to NetBeans and pressing Alt+Shift+F. This will format sql and format php code after, preserving sql formatting. SO instead of a plug in, you're copying, formatting a whole file, copying back and formatting again.
Instead of HeidiSQL, you can use this tool, which is focused on formatting if you are comfortable with web tools like these.
If you want more automation, you can use regular expression support of netbeans to format with backslash n = \n for new line befre each "insert, update delete, select, where and values" terms
running this 6 times will replace all " insert" <- blank plus insert, in your projects with new lines. you can write a regular expression for searching all, "blank plus reserved word", combinations and replace them with new lines.
You can also use it like search for " insert" and repalce with "\n\t insert", which would create a new line an a tab
Considering the question: Is there an IDE that will automatically format sql queries, I must concur with ugurcode. The answer is simple: there isn't any. And with good reason.
Basically an SQL query is nothing but a string in any IDE. Since strings can contain intentional whitespaces and tabs, it would be very bad if an IDE would reformat string content.
The only option that would work for any IDE would be to detect INSERT, UPDATE, DELETE at the start of a string and then format the rest of the string.. ofcourse it would also try to do the same with a string saying "insert quote here..", which once again would be a bad thing.
Since i don't want to leave you with just nothing i will give you advice on a good IDE to choose which does in fact do proper code formatting, code completion, good indentation, plugins etc.. and basically is the best IDE for php development (atleast its the best i've found in my years of professional php development).
Netbeans would be your IDE of choice. It's faster then i.e. Eclipse/PHP, more stable then i.e. codelobster etc.
Log, profile your SQL statements.
Use an external service such as this one - SQLFormat API - in order to format your SQL statements
You can also run it on your machine dowloading the Python sources.
Since your problem is to format an existing body of code, you don't need an IDE. You need a script to batch-process all your files once, and then you can forget about it. This is what the script needs to do:
Correctly parse PHP strings, including strings with all sorts of embedded or escaped quotes. This should be bullet-proof, and should only care about PHP syntax.
Check each PHP string with an algorithm that detects SQL commands. This can be made as smart as you need it to be (no need to blindly accept every string containing the word "insert", for example).
Feed the identified strings through an SQL pretty-printer.
Edit the input file, substituting the formatted string for the original one.
Ideally, parts 1 and 3 should be handled by off-the-shelf modules. The rest should be easy to put together yourself, right?
Update: Explaining this made it sound so simple, I decided to do it myself. Here's a quick solution. It's in python, but if you were willing to switch IDEs you can deal with installing python, right?
Drag-and-drop any number of php files onto the script, or call it from the commandline, and it will filter the SQL bits through the SQLFormat API that #Parahat suggested. It edits the files in place, so keep a copy!
"""Format sql strings embedded in php code, editing source IN PLACE"""
import sys, re, urllib, urllib2
def processfile(fname):
with open(fname) as fp:
text = fp.read()
with open(fname, "w") as out:
for token in chunk(text):
if is_sql_string(token):
token = token[0] + sqlformat(token[1:-1]) + token[0]
out.write(token)
def sqlformat(query):
sqlapi = 'http://sqlformat.appspot.com/format/?keyword_case=upper&reindent=1&n_indents=4&'
return urllib2.urlopen(sqlapi+urllib.urlencode({'data':query})).read()
php_mode = False # global, so that is_sql_string() can examine it
def chunk(src):
"""Chunk the php file into interesting units"""
global php_mode
while src:
if not php_mode: # Read up to the next php group, if any
m = re.match(r".*?<\?php", src, re.S)
if m:
tok, src = _usematch(m, src)
yield tok
php_mode = True
else: # No more php groups: EOF
yield src
return
else: # Reading php code
# PHP ends without another string?
m = re.match(r"[^'\"]*?\?>", src, re.S)
if m:
tok, src = _usematch(m, src)
yield tok
php_mode = False
continue
# at non-string material?
m = re.match(r"[^'\"]+", src)
if m:
tok, src = _usematch(m, src)
yield tok
continue
# Parse a string: Smallest quote-delimited sequence,
# where closing quote is not preceded by backslash
m = re.match(r'".*?(?<!\\)"|' + r"'.*?(?<!\\)'", src, re.S)
if m:
tok, src = _usematch(m, src)
yield tok
continue
# Something I can't parse: advance one char and hope for the best
tok, src = src[0], src[1:]
yield tok
def _usematch(m, inp):
return m.group(), inp[m.end():] # Matched chunk & remaining input
# To recognize an sql command, it MUST begin with one of these words
sql_commands = set("select insert update delete create drop alter declare".split())
def is_sql_string(tok):
if not php_mode or len(tok) < 3 or tok[0] not in set("\"'"):
return False
tokwords = tok[1:-1].split()
return tokwords and tokwords[0].lower() in sql_commands
for fname in sys.argv[1:]:
processfile(fname)
In PHPStorm you can specify SQL dialect for your project: http://www.jetbrains.com/phpstorm/webhelp/sql-dialects.html
Next, you must setup Data Source: http://www.jetbrains.com/phpstorm/webhelp/data-sources-2.html
After that your IDE will support SQL syntax and autocomplete for tables (fields).
Also, there is a page, where you can specify SQL code-style: http://www.jetbrains.com/phpstorm/webhelp/code-style-sql.html
There is no such IDE.
Maybe some SQL is broken into multiple string concatenation, or maybe some SQL is generated using some iterator. Or maybe it contains invalid SQL such as {$_SESSION['admin_id']}.
Your only chance is writing a small script, tuned to match the coding style and possible invalid SQL stuff, which will repair all application source code files. It will take you hours to get it right, but in the end you won't need an IDE which doesn't exist, and you will have a prettyfiend stonified SQL and better source code.
(The above is a solution, thinking you have hundreds of SQL statement throughout the app; if not, just repair them by hand).
Edit: make sure you log all changes in a comparison table, so you can review all which was formatted by your script.
may be nuSphere debugger somehow help you for doing this here is the link nuSphere
Write your queries in MySQL Workebench then edit->format->beautify query
Then paste the query into netbeans, select the test and tab in.
I always used SQLyog to format my SQL statements and paste them back to the IDE, because i didn't find an IDE either, which is able to format sql inside php blocks.
I built a tool to do this for MS SQL Server and C# code. I'd be happy to alter the tool for this purpose for a small fee.
http://www.softfrontiers.com/Downloads/ReIndenter.shtml
An hour or two of my time will save you many hours of frustration.
You can use the tokenizer extension to write a script that would format the SQL.
The following script can be invoked from the command-line, it reads from standard input and writes to standard output. It handles both quoting styles (double or single quotes).
All strings are scanned for possible SQL grammar, based on the starting word, and line breaks are inserted before every keyword; both starting word and keywords are extensible, so go wild :)
<?php
$tokens = token_get_all(file_get_contents('php://stdin'));
function token_value($token)
{
return is_array($token) ? $token[1] : $token;
}
function sql_format($s)
{
if (preg_match("/^(?:select|insert|update|delete)/i", $s)) {
// prefix newline and tab before every keyword
return preg_replace('/\b(from|where|and|order|group by)/i', "\n\t\\0", $s);
}
return $s;
}
$target = '';
$i = 0; $n = count($tokens);
while ($i < $n) {
$token = $tokens[$i];
if ($token === '"') {
$s = ''; ++$i;
while ($i < $n && $tokens[$i] !== '"') {
$s .= token_value($tokens[$i]);
++$i;
}
if ($i < $n) {
++$i;
}
$target .= '"' . sql_format($s) . '"';
} elseif (is_array($token) && $token[0] === T_CONSTANT_ENCAPSED_STRING) {
$quote_style = $token[1][0];
$target .= $quote_style . sql_format(trim($token[1], "'\"")) . $quote_style;
++$i;
} else {
$target .= token_value($token);
++$i;
}
}
echo $target;
You asked:
Is there any program IDE or not that can format MySQL code inside PHP string
with specifically this PHP string definition:
$request1 = "select * from tbl_admin where admin_id= {$_SESSION['admin_id']} and active= 1 order By admin_id Asc";
And the answer is no. There doesn't exist a well use-able settop on a PHP parser in IDEs or on the commandline that works PHP's token_get_all.
With token_get_all you should be able to first of all extract that part that makes sense in your case to be edited. Here with context:
<309:T_VARIABLE> "$request1" <371:T_WHITESPACE> " " "=" <371:T_WHITESPACE> " " """ <314:T_ENCAPSED_AND_WHITESPACE> "select * from tbl_admin where admin_id= " <375:T_CURLY_OPEN> "{" <309:T_VARIABLE> "$_SESSION" "[" <315:T_CONSTANT_ENCAPSED_STRING> "'admin_id'" "]" "}" <314:T_ENCAPSED_AND_WHITESPACE> " and active= 1 order By admin_id Asc" """ ";"
As these tokens show, there is a lot of additional work going to extract that what you call string from it:
$request1 = "select * from tbl_admin where admin_id= {$_SESSION['admin_id']} and active= 1 order By admin_id Asc"
This need to be managed and identified in tokens:
<314:T_ENCAPSED_AND_WHITESPACE> "select * from tbl_admin where admin_id= " <375:T_CURLY_OPEN> "{" <309:T_VARIABLE> "$_SESSION" "[" <315:T_CONSTANT_ENCAPSED_STRING> "'admin_id'" "]" "}" <314:T_ENCAPSED_AND_WHITESPACE> " and active= 1 order By admin_id Asc"
As this example shows, this is not true SQL. So you not only need to find a SQL parser (which exists in PHP, see Parsing sql query PHP), but you also need to make that SQL parser aware of PHP variable substitution like {$_SESSION['admin_id']} in your case. For you it is a variable, for an SQL parser this is just a freaky syntax soup if not an error.
Your small code example is a good one: It already shows that there is no information about the nature of the string that will be substituted. As this information is hidden, a SQL parser will never be able to deal with this string as something well-formed.
So to make my answer "No" more profound: Because no general tools on how to deal with multiple outcome on the higher languages level (the PHP string has multiple probably correct representations in SQL, only the author of the variable content will can tell which one is correct) that already exists, there is no general solution available.
You might want to just fire up some regular expressions on your codebase and blitzshit together an outcome you can feel happy with, and indeed the tools ehime lined-up are worth to consider.
But probably it's worth to invest the time and first extract the strings from the PHP token stream, reformat the string and then proceed outputting the result. That's something perl and regexes can't give you because they don't have the PHP tokenizer.
If there is no support in all the many IDEs for such a thing, there is a reason in most cases. Please consider prepared statements oder object wrappers for your work. I know both things can't be implemented in every system within a few minutes, but your code will become maintainable.
In short: IDEs cant correct design errors. They just make them look nice and colored.
I have used PHPDesigner. i think this will be fulfill what you expecting.
Late to the party, but...
function formatSQL($txt){
$txt = str_replace('SELECT ', "\nSELECT", $txt);
$txt = str_replace(' MATCH', "\nMATCH", $txt);
$txt = str_replace(' AGAINST', "\nAGAINST", $txt);
$txt = str_replace(' OR ', "\nOR", $txt);
$txt = str_replace(' AND ', "\n\tAND ", $txt);
$txt = str_replace(' FROM ', "\nFROM", $txt);
$txt = str_replace(' WHERE ', "\nWHERE", $txt);
$txt = str_replace(' ORDER ', "\nORDER", $txt);
return $txt;
}

Showing latex commands in text string using mathjax

I have a text string, for ex. 'A vehicle travels from A to B, distance {$d} km at constant speed. While returning back to A on same path it {$variation} its speed by {$v} km/hr. The total time of journey is {$t} hours. Find the original speed of vehicle.'
The variables in the curly brackets are to be replaced by appropriate latex equation. I'm using php's preg_replace to replace the variables with latex commands. Unfortunately, my latex commands are coming as it is. It is not processed by mathjax.
For ex, above text becomes 'A vehicle travels from A to B, distance 1 km at constant speed. While returning back to A on same path it increased its speed by (\frac{3}{2}) km/hr. The total time of journey is 1 hours. Find the original speed of vehicle.' The frac is shown as it is.
What is wrong here? Please ask me if you need any more info. Thanks
I'm guessing you aren't quoting the replacement text properly. Replacing just the first two variables, tested using spaweditor's regex tool:
<?php
$string = 'A vehicle travels from A to B, distance {$d} km at constant speed. While returning back to A on same path it {$variation} its speed by {$v} km/hr. The total time of journey is {$t} hours. Find the original speed of vehicle.';
$patns = array();
$patns[0] = '/\{\$d\}/';
$patns[1] = '/\{\$variation\}/';
$repns = array();
$repns[0] = '1 km';
$repns[1] = '\\(\\frac{3}{2}\\)';
echo preg_replace($patns, $repns, $string);
?>
If this doesn't work, show the full example of how you are embedding the text in the page.
Postscript The point being, the latex command for inline maths is \( ... \) - yours is missing the backslashes.

Categories