Úprava krátkého regulárního výrazu první a poslední část textu – Regulární výrazy – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Úprava krátkého regulárního výrazu první a poslední část textu – Regulární výrazy – Fórum – Programujte.comÚprava krátkého regulárního výrazu první a poslední část textu – Regulární výrazy – Fórum – Programujte.com

 

fix0
Stálý člen
27. 10. 2020   #1
-
0
-

Dobrý večer, všem přeji,

@gna mi vytvořil perfektní krátký RE. za který mu moc děkuji:
 

(.*?(;|$)){20}

Ten výraz dělá to, že z textu o struktuře CSV vezme prvních 20 prvků oddělených středníkem, zahodí konec.

Dalo by se to nějak upravit tak, aby to vzalo prvních 10 prvků z textu a posledních 10 textu? Tedy zahazovat střed namísto zahazování konce.

Výsledkem by byla zase strukture CSV, akorát by to zahodilo prvky uprostřed a prvních 10 prvků by se spojilo s těmi posledními 10 prvky.

Jelikož RE nerozumím, tak mě z mé lgiky napadlo něco takového (JE TO SAMOZŘEJMĚ NESMYSL):
 

(.*?(;|$)){10}((;|$).*?){10}

Mohl byste prosím někdo zkušenější to upravit, aby to fungovalo?

Slibuji, že pak dám už s RE pokoj. :-)

Nahlásit jako SPAM
IP: 31.30.175.–
gna
~ Anonymní uživatel
1891 příspěvků
27. 10. 2020   #2
-
0
-

U některého z minulých dotazů jsi měl nějakou vizualizaci/vysvětlení regexu, tak se tam na to podívej. 

,---------------- začátek skupiny
|,--------------- libovolný znak
||,-------------- 0 nebo více opakování
|||,------------- co nejkratší match
||||     ,------- konec skupiny
||||     |
vvvv     v
(.*?(;|$)){10} -- 10 opakování
    ^^^^^
    |||||
    ||||`-------- konec skupiny
    |||`--------- konec dat/řádku
    ||`---------- nebo
    |`----------- středník
    `------------ začátek skupiny

Takže jsi správně poznamenal, že ten tvůj pokus je nesmysl :-)

Nevím kde, jak a k čemu to používáš, tak nevím, jestli půjde ten prostředek nějak vynechat, ale obecně máš prostě AA BB CC a vezmeš si z toho jen AA a CC.

^(([^;]*;){3}).*;(([^;]*;){3})$

Začátek je ve skupině 1 a konec ve skupině 3.

Nahlásit jako SPAM
IP: 213.211.51.–
fix0
Stálý člen
31. 10. 2020   #3
-
0
-

Děkuji za super vysvětlítko, tak nějak jsem zase o kousek blíž příště jednodušší věc zmáknout sám.

Prosím dovysvětlit, pro v původním výrazu není '^' a '$' ?

Oni totiž ty výrazy fungují odlišně. Potřebuji, aby ten druhý fungoval stejně jako ten první.

Problém totiž je v tom, že první výraz mi vrací co potřebuji.

Zatímco druhý výraz vrací vždy zadání bez ohledu na hodnotu pro počet počátečních a koncových prvků. Ono to tedy nenahrazuje, ale možná pouze zkoumá match? Přijde mi, že to co je uprostřed mezi začáteční a koncovou skupinou, tam nemá co dělat. Myslím tím toto '.*;'

Připojen obrázek.

Třešnička na dortu: Pokud řetězec nekončí na delimiter, tak to vyfailuje pro does not match, ale na základě toho, co jsi mi na příkladu ukázal, tak mi došlo, že to lze jednoduše ošetřit tímto rozšířením:

^(([^;]*(;|$)){3}).*;(([^;]*(;|$)){3})$
Nahlásit jako SPAM
IP: 31.30.175.–
gna
~ Anonymní uživatel
1891 příspěvků
31. 10. 2020   #4
-
0
-

Ano, regex sám o sobě nic nenahrazuje, jen napasuje popsaný vzor na data. Když to má začátek/prostředek/konec (ABC), tak to musíš popsat všechno a pak si z toho vytáhneš, co chceš (AC).

Připojen obrázek.

Nahlásit jako SPAM
IP: 213.211.51.–
peter
~ Anonymní uživatel
4016 příspěvků
1. 11. 2020   #5
-
0
-

- z textu o struktuře CSV
- (.*?(;|$)){20}

To mas ale uplne spatne.

1. csv ma konkretni zpusob zapisu, escapovani a zvlast to plati pro textove polozky. Treba, kdyz text obsahuje strednik nebo zalomeni na dalsi radek. To ten vyraz vubec nezachycuje. Ani nemuze. Csv se totiz parsuje jinak.

2. pokud vynechas bod 1 a budes uvazovat csv bez escapovani, pak, co ti brani nacist soubor radek po radku? Php na to ma funkce. A pak pouzijes  

$sloupce = explode(';', $radek)

3. znacka ^ oznacuje zacatek hledani a $ konec. Kdyz je neuvedes, najde to prvni odpovidajici text. Coz gna vyraz opet plne dostacuje na zadani, ktere popisujes, pri vynechani bodu 1 [skutecne spravne parsovani csv]. Pokud jsi ale zmenil zacani, neco ze zacatku a neco z konce, pak tam musi byt ty znacky.

(.*?(;|$)){20}

(^(.*?(;|$)){10})|((.*?;|$){10}$) - mohlo by to byt nejak takto

Ale, jak rikam, i tak je to spatne, ani se nebudu snazit takove reseni dotahnout do konce. Najdi si v php parser pro csv, jinak na csv muzes zapomenout, ze ho nekdy spravne nactes :)
https://www.php.net/…csv.php ;



<!-- Example #1 Read and print the entire contents of a CSV file -->
<?php
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data);
        echo "<p> $num fields in line $row: <br /></p>\n";
        $row++;
        for ($c=0; $c < $num; $c++) {
            echo $data[$c] . "<br />\n";
        }
    }
    fclose($handle);
}
?>
Nahlásit jako SPAM
IP: 193.84.198.–
fix0
Stálý člen
5. 11. 2020   #6
-
0
-

gna:

No ten funkční příklad je tedy AB se selekcí A.
Nyní mám ABC, ale neumím selektovat AC.

peter:

Proč myslíš, že je to špatně, mě to funguje.

  1. Není to CSV, pouze text skrukturou podobný CSV, vyjma tedy toho, že může končit středníkem (resp. custom delimiterem).
  2. V PHP bych tuhle úlohu měl hotovou hned právě pře zmíněnou funkci explode. Problém je v tom, že nemám k dispozici PHP, mohu pracovat pouze s RE. Nedělám webovou aplikaci.
  3. PHP parser by jistě byla nejvíce korektní cesta. Má to dva háčky. Nedělám webovou aplikaci PHP natož PHP parser je úplně mimo téma. Dalším háčkem je to, že já přece nemám doslova CSV.

Všichni:

No ještě si vygooglím pár souvislostí a zkusím si brzy vyhradit několik hodin a nějak to zkusit vykoumat a odladit. :-D

Nahlásit jako SPAM
IP: 31.30.175.–
peter
~ Anonymní uživatel
4016 příspěvků
6. 11. 2020   #7
-
+1
-
Zajímavé
fix +

Struktura CSV znamena plny CSV. Mimochodem, lepsi format pouzivaji sql, ktere proste klicovy znak zdvovuji. Spatne je to prave proto, ze csv ma jinou syntaxy. Ale ok, kdyz je tomu jinak.

Jak jsem psal, mohlo by to byt nejak takto. Tam je to uz pak jen o zavorkach 

(^(.*?(;|$)){10})|((.*?;|$){10}$)

(.*?(;|$)){10}
.* vyber jakykoliv text
;|$ strednik nebo konec puvodniho stringu
? v tomto pripade znamena hledej, dokud nenarazis na vyraz v zavorce
a cely tenhle vyraz ozavorkujes a chces jej 10x
( .* ? ( ;|$ ) ) {10}

Jenze, takhle napsane, kdyz bude pocet mensi nez 10, tak ti vrati mensi
 pocet. Jinak napsane, bez $, ti vrati nic pri mensim poctu. Otazkou je, jak
moc se muzes spolehnout na to, ze tam bude minimalne 10 shod.

No, a kdyz chces od zacatku a konce, tak to je jen o pridani ^ a $ a dalsich
 zavorek (ty mezery tam davam navic, zamerne, aby bylo videt rozdil, ale ty si je odmaz)
(^ (.*?(;|$)){10} )
( (.*?(;|$)){10} $)
A mezi oba vyrazy pak musis dat "nebo" symbol | a nebo .*?
(^ (.*?(;|$)){10} ) | ( (.*?(;|$)){10} $)
(^ (.*?(;|$)){10} ) .*? ( (.*?(;|$)){10} $) -- ale v tomhle pripade bys musel
 mit na vystupu "$1$2", vypis jen zavorek

No, a kdyz bys mel vzdy za stringem strednik, i za poslednim, tak by to slo napsat i takto
(^ (.*?;){10} ) | ( (.*?;){10} $)
.*?; - vyber kazdy znak, dokud nenarazis na ;
Nahlásit jako SPAM
IP: 193.84.198.–
fix0
Stálý člen
11. 11. 2020   #8
-
0
-

Abych odpověděl důležité otázky:

  • Za každým prvkem je středník
  • Vyjma posledního prvku, za tím středník být nemusí
  • Každý řetězec prvků má N prvků, tedy i méně než je požadované množství. Když jich požaduji prvních 10, je potřeba, aby to vrátilo třeba jen jeden, pokud v tom řetezci zrovna bude sám. Nebo dva. Tedy vralstně jich nechci prvních 10, ale chci jich první 1-10, podle prvků v tom poli.

Další věc, co mě napadla, kterou by se to mělo dost zjednodušit je:

  • AA = Zajistit RE pro prvních 1-10, teoreticky ho mám, ale takhle se to asi použít nedá: (.*?(;|$)){1-10}.
  • CC =zajistit RE pro posledních 1-10, teoreticky bych to mohl zvládnout sestrojit z toho, co jsi mi krásně ukázal, takže asi není problém. Viděl bych to nějak takto: ^.*;(([^;]*;){1-10})$, ale samozřejmě taky nesmysl

Řešení: Když si takto separátně uložím prvních 1-10, a zvlášť posledních 1-10, Můžu pak ty dva výsledky spojit výsledek = AA + BB, jediné, co by nedělalo dobrotu, kdyby řetězec obsahoval <20 prvků, pak by vznikaly duplicity, protože počáteční prvky by byly zároveň těmi koncovými. Ale to mi vůbec nevadí, nad výsledným stringem se dále volá rutina, která odstraní duplicitní prvky.

Příklad #1:

  • Řetězec = "1;2;3;4;5;6;7;8;9"
  • AA RE (nefukční) = (.*?(;|$)){1-3}
  • AA{1-3} = 1;2;3;
  • CC RE (nefukční) = ^.*;(([^;]*;){1-3})$
  • CC{1-3} = 7;8;9;
  • Výsledek = 1;2;3;7;8;9;

Příklad #2:

  • Řetězec = "1;2;3;"
  • AA RE (nefukční) = (.*?(;|$)){1-2}
  • AA{1-2} = 1;2;
  • CC RE (nefukční) = ^.*;(([^;]*;){1-2})$
  • CC{1-2} = 2;3;
  • Výsledek = 1;2;2;3;

Nahlásit jako SPAM
IP: 31.30.175.–
peter
~ Anonymní uživatel
4016 příspěvků
15. 11. 2020   #9
-
0
-

   

1-3 se zapisuje jako {1,3}
min 1, max 3

(A).*?(B)
A = ^(.*?(;|$)){1,10})
B = ((.*?(;|$)){1,10}$
Nahlásit jako SPAM
IP: 193.84.198.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 1 host

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý