Portál AbcLinuxu, 6. prosince 2025 15:21
:/nějaká/cesta/soubor.abc. Potřebuji capture na část nějaká/cesta/soubor.abc. Problém je, že jednoduchý regex mi pak matchne v řetězci return ":/nějaká/cesta"; const char *a = ".txt"; část ":/nějaká/cesta"; const char *a = ".txt, což je špatně. Musím to tedy udělat přísněji. Cesta je buď v dvojitých uvozovkách, v jednoduchých uvozovkách, v html/xml tagu nebo v css v závorkách (např. url(:/bla/bla.abc)). A to je problém. Chtěl bych to mít jako jeden regex, kde by to bylo zkombinované. Nějak bych to nakombinoval s or operací, ale pak bych měl třeba na ":/moje/cesta.abc&t;/tag> match, což také nechci.
Nejdále jsem se dostal k regexu (["']:\/|>\s*?:\/|\(:)(.*?)(["']|\s*?<|\)) (můžete vyzkoušet třeba na regex101.com). Jenže to matchuje i to, co nechci.
":/moje/cesta.abc" ':/moje/cesta.abc' <url>:/moje/cesta.abc</url> <bla><a>:/moje/cesta1.abc<b>:/moje/cesta2.abc</bla> neco: url(:/moje/cesta.abc) ":/moje/cesta.abc' // nechci match <url>:/moje/cesta.abc' // nechci match
Tak je lze pojmenovat. Navíc pravděpodobně půjde regexp složit s řetězců. Tak můžete napsat obdobu následujícího Perl one-lineru:
perl -nE '
BEGIN {
my $cesta = ":(?<cesta>.*?)";
our $rx= join "|", map {sprintf $_, $cesta} (q{"%s"}, q{\'%s\'}, q{>%s<}, q{\(%s\)});
say $rx
};
say $+{cesta} while /$rx/g
' /tmp/pom.txt
":(?<cesta>.*?)"|':(?<cesta>.*?)'|>:(?<cesta>.*?)<|\(:(?<cesta>.*?)\) /moje/cesta.abc /moje/cesta.abc ...
$cesta = ":(?<cesta>.*?)";
@maska=qw{ "cesta" 'cesta' >cesta< \(cesta\) };
s/cesta/$cesta/ foreach @maska;
$rx= join "|", @maska;
":/moje/cesta.abc' <url>:/moje/cesta.abc'
<url>:/cest/a)
:/ a ostatní jsou prázdné. Ale je to pokrok, děkuji.
((["'])|[>\(]):\/(.*?)(\2|[<\)])Přínosem v řešení je dekompozice stop-tokenů od match-textu. Tím vznikne kratší zápis, který je i přehlednější. Čímž neříkám, že původní zápis byl špatný. Nuže, posuďte teď můj. Bye.
\2 teď vidím poprvé, netušil jsem, že něco takového jde.
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.