[megoldva] profi preg-esek segitseg! exec sp_executesql-hez kell

sziasztok,

kellene egy regularis kifejezes, ami kicsereli egy stringben a "?" jeleket, de csak akkor, ha nincs aposztrofok kozott.

print preg_replace("regularis kifejezes", "Q", "? '?' ? 'barmi?' ? '?valami' ? 'akar?mi'");

a kimenet a kovetkezo lenne:

Q '?' Q 'barmi?' Q '?valami' Q 'akar?mi'

koszi!

azta mennyi jo otlet/megoldas! ugyesek vagytok!

update:

viszont ha mar group van, azt lehet tudni hogy hanyadik talalat?

mert a vegen @P1, @P2, @P3, stb-ra kell lecserelnem a "?"-t, hatha megy 1 utasitassal.

tehat ez lenne a vegleges string:

@P1 '?' @P2 'barmi?' @P3 '?valami' @P4 'akar?mi'

ebbol mar biztos latszik, hogy parameteres query-t akarok csinalni, es "exec sp_executesql"-el vegrehajtani.

az sqlsrv driverrel mar igy csinalja, de ahol meg php-sybase van, ott nekem kell ezt megoldanom.

sajnos php5 alatt nekem nem fordul egyik verzioja sem az sqlsrv-nek "pecl install sqlsrv", meg az a verzio sem ahol nem dobtak a php5 tamogatast, meg ki tudja azota mennyi hibajavitas van benne, igy marad a php-sybase, es kulon megcsinalni a parameteres query-t.

koszi!

update2:

a dupla aposztrofok nem szamitanak aposztrofnak, de szovegen (aposztrofon) belul helyezkedhetnek el.

pl. '''' (4 aposztrof) az aposztrofok kozott levo 1db aposztrof amit egy masik aposztrof escapel.

vagy pl. 'it''s' = "it's" szoveg aposztrofok kozott.

update3:

hopp, meg vannak meg megjegyzesek "--"-vel kezdodoen sorvegig, stb.

talan a legjobb az lenne, ha megneznem az sqlsrv forrasat, ott mar elvileg megoldottak.

update4:

csak azert irom hogy megoldva, hogy ne turaztassatok magatokat rajta, ennyibol mar menni fog.

koszi!

Hozzászólások

<?php
$search = '?';
$replace = 'Q';
$input = "? '?' ? 'barmi?' ? '?valami' ? 'akar?mi'";

$regex = '~\'.*?\'(*SKIP)(*FAIL)|' . preg_quote($search, '~') . '~s';
$output = preg_replace($regex, $replace, $input);
echo $output;

Innen loptam:

https://stackoverflow.com/a/20767638

Szerkesztve: 2022. 12. 22., cs – 20:08

Nem biztos, hogy mindent regexp-pel kell megcsinálni. Végigvánszorognék egy ciklussal a szövegen karakterenként. Kezdetben az idézet nevű változóm 0 lenne, ha meglátnék egy aposztrofot, akkor 0 esetén 1-gyé, 1 esetén 0-vá változtatnám, ezzel tudnám, mikor vagyok aposztrofok között. Ha meglátnám a kérdőjelet és az idézet nevű változóm 0 értékű, akkor lecserélném Q-ra.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Aztán mit nyersz vele, ha lesz egy olvashatatlanul bonyolult regexped, ami ha bugos, akkor sem tudod kijavítani úgy, hogy biztos légy abban, jó lesz? Amit írtam, egy nyúlfarknyi függvény, annak meghívása pedig ugyanúgy egy utasítás lesz. Ellenben áttekinthető, karbantartható, érthető a működése. Aztán lehet tovább bonyolítani azzal az esettel, ha escape-elve van az aposztrof, meg ilyesmi, ha van rá igény.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Itt már lassan megszokottá válik, hogy csak ellenszegülni, egyet nem érteni szabad. Nem csak akkor szólok egy adott témához, ha valakinek a hozzászólásával nem értek egyet, hanem akkor is, ha csak úgy eszembe jut róla valami. Szóval mi most nem vitatkozunk, hanem ugyanarról beszélünk szerintem. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Szerkesztve: 2022. 12. 22., cs – 21:48

siman negative lookbehind es lookahead

ilyesmi:

$  echo -n "? '?' ? 'barmi?' ? '?valami' ? 'akar?mi'" | php -r 'var_dump(preg_replace("#(?<" . chr(33) . chr(39) . ")\?(?" . chr(33) . chr(39) . ")#", "Q", file_get_contents("php://stdin")));'
string(40) "Q '?' Q 'barmi?' Q '?valami' Q 'akarQmi'"

ugyebar (?<!') es (?!') lenne, csak nem akartam p@csolni a bash escape-ekkel

'akar?mi' => ez (marmint a kerdojel) nincs aposztrofok kozott, akkor miert cserelni?

Hm... csak egy akademikusabb erdeklodes: hogy lehetne megcsinalni ezt regexppel, ha a \-sel kiescape-lt apsztrofok viszont nem szamitanak aposztrofnak? Avagy tenylegesen hol vannak az elmeleti es/vagy gyakorlati hatarai, amikor pl locsemege altal fentebb emlitett ciklusos megoldas mar hatekonyabb es/vagy "uzembiztosabb"? 

Szerkesztve: 2022. 12. 30., p – 12:22

Én ott akadtam el, hogy PHP5... Ha jól olvasom az internetet, akkor 2019. jan. 1-óta unsupported.
Szerk: Nem teszteltem, de talán ilyesmire gondolsz:

<?php
    function PlaceHolderQmToAt($str, &$cnt) {
        $len= strlen($str);
        $state= 0;
        $statebs= 0;
        $to= '';
        for ($i=0; $i<$len; ++$i) {
            $c= $str[$i];
            if ($statebs==1) {
                $statebs= 0;
            } else if ($c=='\\') {
                $statebs= 1;
            } else if ($c=='\'') {
                $state= 1-$state;
            } else if ($state==0 && $c=='?') {
                $c= sprintf('@%d', $cnt++);
            }
            $to .= $c;
        }
        return $to;
   }

    $from= "SELECT * FROM table".
          "\nWHERE field1=? AND field2='?'".
          "\n AND field3='Sej? Haj\\'?\\''".
          "\n AND field4=?+'Suffix'";
    printf("From:\n%s\n", $from);

    $cnt= 1;
    $to= PlaceHolderQmToAt($from, $cnt);
    printf("To:\n%s\n", $to);
?>

Az apostolokon belüli apostolok gondját kétféleképpen szokás kezelni: vagy \backslash jellel védve, vagy duplázva. Pl: 'első \'idézet\' ilyen', 'második ''idézet'' ilyen'.
A fenti program az első esetre van felkészítve.

Ilyen lenne a másik változat:

#!/usr/local/bin/php
<?php
# ez a valtozat a duplazott idezojelekre van felkeszitve
# 'Petofi irta ''Ej, mi a ko, tyukanyo kend'' hires verseben'

    function PlaceHolderQmToAt($str, &$cnt) {
        $len= strlen($str);
        $state= 0;
        $to= '';
        for ($i=0; $i<$len; ++$i) {
            $c= $str[$i];
            if ($state==0) {
                if ($c=='\'') $state= 1;
            } else if ($state==1) {
                if ($c=='\'') $state= 2;
            } else if ($state==2) {
                if ($c=='\'') $state= 1;
                else          $state= 0;
            }
            if ($state==0 && $c=='?') {
                $c= sprintf('@%d', $cnt++);
            }
            $to .= $c;
        }
        return $to;
    }

    $from= "SELECT * FROM table".
          "\nWHERE field1=? AND field2='?'".
          "\n AND field3='Sej? Haj''?'''".
          "\n AND field4=?+'Suffix'";
    printf("From:\n%s\n", $from);

    $cnt= 1;
    $to= PlaceHolderQmToAt($from, $cnt);
    printf("To:\n%s\n", $to);
?>