PDA

View Full Version : Resolved looking to simplify a bit of pcre



james438
07-28-2013, 10:55 PM
$clmns2 = preg_replace('/^date,/',"cast(date as char),",$clmns2);
$clmns2 = preg_replace('/,date,/',",cast(date as char),",$clmns2);
$clmns2 = preg_replace('/,date$/',",cast(date as char)",$clmns2);

I was trying to write the above on one line, but couldn't so I ended up writing it as you see above. Any ideas on how this code could be condensed?

traq
07-29-2013, 12:04 AM
alternating lookahead:

$regexp = '#(?|(^date,)|(,date,)|(,date$))#';
Captures any of the patterns you described (all backreferenced as $1).

However, preg_replace (http://php.net/preg_replace)() won't work this way.

Arg #1 is $pattern (the regexp).

Arg #2 is $replacements (the replacement pattern). You have an empty string - basically, if the pattern matches, you're asking to delete it (is that what you want? if so, using str_replace (http://php.net/str_replace)() would be much faster).

Arg #3 is $subject (the string to match against the pattern). You have the return value of the function cast(). This isn't a PHP function. Do you have such a function defined? Also, you're passing the args date, as, and char -all constants- to this function. Did you mean those to be a string? or variables? As-is, this should be throwing a parse error.

Arg #4 is $limit (the max number of replacements to make). This must be an integer; you've passed the variable $clmns2 (same var you're assigning the return value to).

Can you explain a bit about what you're trying to do?

james438
07-29-2013, 01:49 AM
For the backstory I am looking to update my search script a little. Initially I wanted to be able to search the ID column of a particular table, but in order to search a column set in integer format I need to cast it as character so that I can search it like text.

I had forgotten about it until I updated my search program to search a "date" column that was set in datetime format and discovered that I was getting an odd number of results. After looking into it more closely I soon realized that I needed to cast the date column as char or cast(date as char). I'm using the pcre I listed to generate a small part of a query for the search script I use on my site.

I tried using str_replace to replace the instances of date and date2, but if I replace date I also replace date2. It also does not account for whether the occurrence occurs at the beginning, middle, or end of the string.

Another option which hadn't occurred to me is to use explode and then do a search and replace of all of the occurrences of date and date2 in the array, but I suspect I'd still have to jump through another hoop just to replace the occurrences of date rather than date2.

So that leaves me with my current situation. It works now, but I am having trouble simplifying my pcre, which is not really necessary, but it seems like I should be able to do it. When I used your script as well as the way I tried it earlier it wasn't remembering the location of the commas in my string.

The string is a long list of column names separated by a comma. Here is an example of my string that I need to format:


$clmns="ID,title,body,ID,title,basic_premise,summary,conclusion,ID,title,summary,ID,ID,verse,ID,ID,summary,ID,ID,summary,ID,ID,date,summary,ID,title,summary,date,date2";

$clmns2="title,body,title,basic_premise,summary,conclusion,title,summary,ID,verse,ID,summary,ID,summary,ID,date,summary,title,summary,date,date2";

After being formatted it should look like this:


$clmns="cast(ID as char),title,body,cast(ID as char),title,basic_premise,summary,conclusion,cast(ID as char),title,summary,cast(ID as char),cast(ID as char),verse,cast(ID as char),cast(ID as char),summary,cast(ID as char),cast(ID as char),summary,cast(ID as char),cast(ID as char),cast(date as char),summary,cast(ID as char),title,summary,cast(date as char),cast(date2 as char)";

$clmns2="title,body,title,basic_premise,summary,conclusion,title,summary,cast(ID as char),verse,cast(ID as char),summary,cast(ID as char),summary,cast(ID as char),cast(date as char),summary,title,summary,cast(date as char),cast(date2 as char)";?>

The full code snippet I am currently using is:


$clmns2 = str_replace("ID","cast(ID as char)",$clmns2);
$clmns = str_replace("ID","cast(ID as char)",$clmns);

$clmns2 = preg_replace('/^date,/',"cast(date as char),",$clmns2);
$clmns2 = preg_replace('/,date,/',",cast(date as char),",$clmns2);
$clmns2 = preg_replace('/,date$/',",cast(date as char)",$clmns2);
$clmns2 = preg_replace('/^date2,/',"cast(date2 as char),",$clmns2);
$clmns2 = preg_replace('/,date2,/',",cast(date2 as char),",$clmns2);
$clmns2 = preg_replace('/,date2$/',",cast(date2 as char)",$clmns2);

$clmns = preg_replace('/^date2,/',"cast(date2 as char),",$clmns);
$clmns = preg_replace('/,date2,/',",cast(date2 as char),",$clmns);
$clmns = preg_replace('/,date2$/',",cast(date2 as char)",$clmns);
$clmns = preg_replace('/^date,/',"cast(date as char),",$clmns);
$clmns = preg_replace('/,date,/',",cast(date as char),",$clmns);
$clmns = preg_replace('/,date$/',",cast(date as char)",$clmns);

james438
07-29-2013, 02:36 AM
kk, I fixed a bit of code above. My examples had no listings of date or date2.

Odd, in Opera the last line of my second example is cut off. Oh, well.

traq
07-29-2013, 02:47 AM
... I soon realized that I needed to cast the date column as char or cast(date as char).

AHH, I misread your original code. I thought it was (e.g.):
$clmns = preg_replace('/,date$/','',cast(date as char),$clmns);but it is really:
$clmns = preg_replace('/,date$/',",cast(date as char)",$clmns); Sorry!

So, this is going to be used in an SQL statement?


I tried using str_replace to replace the instances of date and date2, but if I replace date I also replace date2. It also does not account for whether the occurrence occurs at the beginning, middle, or end of the string.You're right; forgot about that.


... When I used your script as well as the way I tried it earlier it wasn't remembering the location of the commas in my string.
yeah; I didn't realize you wanted to keep them:
$pattern = '#(?|(^date)(?:,)|(?:,)(date)(?:,)|(?:,)(date$))#';

james438
07-29-2013, 03:23 AM
No worries, I figured there was a bit of misunderstanding, so I elaborated on what I was trying to do. I find that can help to make the code easier to visualize.

I tried what you gave and a few more ideas of my own and I am just not getting it to work. How would you implement it? What does ?| do?

traq
07-29-2013, 03:48 AM
What does ?| do?
it's a non-capturing subpattern: it matches against the string, but does not create a backreference. However, I don't think you actually need it.


I tried what you gave and a few more ideas of my own and I am just not getting it to work. How would you implement it?
I had to read it a few times, but I think I understand now what you're trying to do.

1) Are the words "ID", "date", and "date2" all you need to match (i.e., any other options you need to cover)?
2) Are you including the comma only as a delimiter (e.g., to prevent "date" from matching "date2")?

If so, we can use a much simpler regexp. \b is a "word boundary" - zero-width, but matches the start or end of a word. So, we can use that as a delimiter, and just put the desired words in an alternating group:
<?php

$string = "ID,title,body,ID,title,basic_premise,summary,conclusion,ID,title,summary,ID,ID,verse,ID,ID,summary,ID,ID,summary,ID,ID,date,summary,ID,title,summary,date,date2";
$pattern = '#\b(date|ID|date2)\b#';
$replace = 'cast($1 as char)';

$new_string = preg_replace( $p,$r,$s );

print $new_string;

tested.
cast(ID as char),title,body,cast(ID as char),title,basic_premise,summary,conclusion,cast(ID as char),title,summary,cast(ID as char),cast(ID as char),verse,cast(ID as char),cast(ID as char),summary,cast(ID as char),cast(ID as char),summary,cast(ID as char),cast(ID as char),cast(date as char),summary,cast(ID as char),title,summary,cast(date as char),cast(date2 as char)

james438
07-29-2013, 04:06 AM
Yes! I had completely forgotten about \b! I don't code very often these days, so I'm getting slowly rustier, which is fine. Thanks again :)

Out of curiosity what part did you have to read through a few times? Was it the odd code I posted? When I first posted it my example strings were a little incorrect.

traq
07-29-2013, 04:27 AM
Out of curiosity what part did you have to read through a few times?

I've been overworking myself for the last few weeks, so from time to time I'm having difficulty reading most things. :) I actually gave up on the sentences and started comparing your "before" and "after" strings.

Glad I could help!