Üdv!
A perlre doksi szerint ha egy selector többször is értéket kap akkor az utolsó-t lehet kiolvasni belőle...
Egy bonyolultabb kifejezésben lenne szükségem arra hogy minden értékét megkapjam (mondjuk egy array-ba vagy ilyesmi) anélkül hogy szét kellene split-elnem a stringet.
Tehát pl ha ez után:
$text = 'aaa bbb ccc';
$text =~ /(?:(\w+)\s*)*/;
$1 értéke ['aaa', 'bbb', 'ccc'] lenne 'ccc' helyett
- 998 megtekintés
Hozzászólások
Én valahogy így oldanám meg:
($temp = $text) =~ s/(\w+)\s*/$eredmeny[$i++]=$1/ge;
- A hozzászóláshoz be kell jelentkezni
Valoszinuleg a
/g
modifiert keresed, probald ki ezt:
$ perl -lE '$text = "aaa bbb ccc"; @matches = ( $text =~ m/\w+/msg ); say for @matches'
- A hozzászóláshoz be kell jelentkezni
köszi de mint írtam egy nagyobb kifejezés belsejében lenne szükség ilyen többszörös kiválasztásra
- A hozzászóláshoz be kell jelentkezni
Egy kis modositassal hasznalhato arra is:
$ perl -lE '$text = "aXXa bYYb cZZc"; @matches = ( $text =~ m/\w(\w+)\w/msg ); say for @matches'
update:
Azt hiszem felfogtam, mit is akarsz elerni:
$ perl -lE '$text = "aaa bbb ccc"; $text =~ m/ (?: (\w+) (?{ push @matches, $1 }) \s* ) * /xms; say for @matches'
- A hozzászóláshoz be kell jelentkezni
Igen köszi én is az utóbbival kezdtem el kísérletezni tegnap, és egyenlőre úgy tűnik működik!
- A hozzászóláshoz be kell jelentkezni
Meg egy apro megjegyzes: jobb lett volna ha a
$1
helyett
$+
-t irok a
(?{ })
reszben, de ez addig nem szamit, amig nem akarsz tobb capturing zarojelet hasznalni.
- A hozzászóláshoz be kell jelentkezni
Hali!
Igazából a végeredmény így néz ki: http://hup.pastebin.com/m50998dd1
Viszont kérdeznék még :)
$+ micsoda?
a fenti kód mér ad ilyen warningokat?
Variable "%attrs" will not stay shared at (re_eval 574) line 1.
egyébként hibátlanul működik :)
ilyen bb szerü tag-eket olvasgatok ki vele:
[valami]
[valami=ertek]
[valami attr=ertek]
[valami attr="érték"]
...
és a többszörösség ott jön a képbe hogy több attribútum is lehet.
Köszi a segítséget!
- A hozzászóláshoz be kell jelentkezni
Kezdjuk az egyszerubbel:
A
$+
valtozo a legutolso matchelo capturing zarojel tartalmara hivatkozik, bovebben lasd
perldoc perlvar
.
The text matched by the last bracket of the last successful search pattern. This is useful if you don’t know which one of a set of alternative patterns matched. For example:
/Version: (.*)|Revision: (.*)/ && ($rev = $+);
Az emlitett warning legegyszerubb elofordulasa valami ilyesmi:
#! /usr/bin/perl
use strict;
use warnings;
#no warnings 'closure';
sub foo {
my $var = 0;
sub bar {
++$var;
print "bar: $var\n";
}
++$var;
print "foo: $var\n";
}
bar();
foo();
__END__
A kimenet:
Variable "$var" will not stay shared at ./hup.id.83056 line 10.
bar: 1
foo: 1
Azaz ha egymasba agyazott nevesitett szubrutinokat hivsz, akkor a belso sub a kulsoben lexikalis valtozokat nem abban az allapotban latja, amiben a kulso (azaz "not stay shared"). Ez azert van, mert a nevesitett sub nem lexikalis, igy a bar() mar akkor is definialt, amikor a foo() meg le sem futott. Epp ezert ezt ugy szoktak elkerulni, hogy a beagyazott sub mindig legyen nevtelen (
sub {}
), es igy lexikalis.
Ha biztos vagy benne, hogy a warning nem jelez valodi hibat, akkor elnyomhatod a kikommentelt
no warnings 'closure'
-rel.
Szoval ennek fenyeben gondold vegig, hogy mi van a linkelt kodreszlet elott es utan. (Ha jol sejtem egy nevesitett sub()-ban van az egesz pastebinen levo kod.)
Aztan figyelj arra is, hogy a
perldoc perlre
szerint experimental a
(?{ })
konstrukcio, ha jol tudom, fokepp a kulonbozo lexical scoping issuek nem kielegito kezelese miatt.
Ezt a problemat ugy lehet megkerulni, hogy nem lexikalis valtozot hasznalsz (azaz
my %attrs
helyett
our %attrs
), es a
(?{ })
konstrukcion belul pedig mindig lokalizalod a hasznalt valtozokat, hogy a regex engine backtrackingje se kavarjon be.
De javaslom inkabb olvasd el ezeket, mert fokepp az elsoben sok minden tisztabb, mint ahogy en probalom magyarazni:
egy nagyon hasznos thread a perlmonks.org-rol
perldoc (?{ })
perldoc use re eval
Tovabba en a helyedben azert megneznem a CPAN-on levo BBCode-Parser-t kozelebbrol, mert valoszinuleg sokkal konnyebben olvashato es karbantarthato kodot tudnal irni azt felhasznalva.
- A hozzászóláshoz be kell jelentkezni
Tegnap ota atgondoltam alaposabban, hogy milyen problemak lehetnek a kododdal. Amit az elozo hozzaszolasban irtam az alapvetoen jo, de kisse osszemostam ket kulonbozo problemat.
1) Az elso gond az lehet, amit a "will not stay shared" warning jelez. A megoldas az, hogy a
(?{})
blokkban ne hasznalj soha lexikalis valtozokat, hanem helyettuk package global valtozokat.
Vagyis alapesetben:
$refText = 'foo[tag param="value"]';
our %attrs;
$$refText =~ ...
Viszont ha a kodod olyan kornyezetben van, hogy ismetlodoen futhat (azaz tobb mint egyszer, peldaul egy sub{}-ban, amit sok helyrol hivsz), akkor az our keves, es erre van szukseg:
sub parse_bb_tag {
$refText = \shift;
local our %attrs;
$$refText =~ ...
}
Ha nem hasznalod a localt, akkor a korabbi parse_bb_tag() hivasok key/value ertekei is szerepelni fognak az %attrs hashben.
2) regex engine backtracking vs.
(?{})
Ezt lusta leszek leirni, de a mar korabban is linkelt threadben itt talalsz jol ertheto peldat arrol, hogy mi a gond, es megoldast is ra. Ha ez meg nem lenne eleg egyertelmu, akkor olvasd hozza a perlre dokumentaciobol azt a bekezdest, ami igy kezdodik: The "code" is properly scoped in the following sense...
- A hozzászóláshoz be kell jelentkezni