webForumDet fria alternativet

Regular expressions för att få ut data

.NET

15 svar · 820 visningar · startad av lilja

Medlem sedan juli 20041 183 inlägg
Frågan#1

Jag försöker plocka ut information från strängar och räkna ihop vad summan blir av informationen i alla strängar, men har problem med dels hur jag ska få ut data och dels hur jag ska spara informationen temporärt. Det svåraste är dock hur jag ska få ut informationen och jag gissar på att det kan göras smidigt med ett regular expression? :) Raderna kan se ut såhär:

July 1 of YR6  	 Meteors rain across the lands and kill 325 peasants, 2 Warriors, 124 Axemen and 47 Berserkers!
July 8 of YR6  	 Meteors rain across the lands and kill 181 peasants, 1 soldier, 1 Warrior, 82 Axemen and 32 Berserkers! 

July 1 of YR6  	 Meteors rain across the lands and kill 325 peasants, 2 Rangers, 124 Archers and 47 Elf Lords!

Notera att namnen förekommer i singular och plural (soldier och soldiers) och att sista typen kan ha mellanslag i namnet. I mitt exempel finns både Berserkers och Elf Lords men i riktiga kommer bara en av dem att förekomma per anrop.

Det jag vill är alltså att summera "förlusterna" för alla raderna. I dagsläget sparar jag information i en hashtable men det kanske finns bättre sätt och jag har stora problem med att plocka ut värdena (via regular expressions?).

En del känner kanske igen detta, kommer från ett gammalt MMORPG kallat Utopia. :)

Medlem sedan juni 20019 519 inlägg
#2

Oj, Utopia var beroende på det för många år sedan, var med i en rätt stor grupp av riken back in the days.

Det du egentligen bara vill är att få ut alla tal efter July x of yrx [xxxxx] (det som står i [xxxx]? Eller är det grupper så du vill få reda på hur många warriors, axmen etc du har förlorat totalt?

(?:(\d+) peasants?)

kommer ge dig tre matches, 325, 181 och 325

Medlem sedan juli 20041 183 inlägg
#3

Jag vill kunna skriva ut ""Meteors killed 794 peasants, 6 Warriors, 416 axmen and 160 Elf Lords" av följande:

July 5 of YR6  	Meteors rain across the lands and kill 324 peasants, 2 Warriors, 118 Axemen and 45 Elf Lords!
July 6 of YR6 	Meteors rain across the lands and kill 34 peasants, 1 Warrior, 76 Axemen and 29 Elf Lords!
July 7 of YR6 	Meteors rain across the lands and kill 173 peasants, 1 soldier, 2 Warriors, 119 Axemen and 46 Elf Lords!
July 8 of YR6 	Meteors rain across the lands and kill 181 peasants, 1 soldier, 1 Warrior, 82 Axemen and 32 Elf Lords!
July 9 of YR6 	Meteors rain across the lands and kill 82 peasants, 21 Axemen and 8 Elf Lords!

EDIT: Och namnen på enheterna varierar beroende på vilken ras man valt.

Medlem sedan juni 20019 519 inlägg
#4

lilja skrev:

Jag vill kunna skriva ut ""Meteors killed 794 peasants, 6 Warriors, 416 axmen and 160 Elf Lords" av följande:

July 5 of YR6  	Meteors rain across the lands and kill 324 peasants, 2 Warriors, 118 Axemen and 45 Elf Lords!
July 6 of YR6 	Meteors rain across the lands and kill 34 peasants, 1 Warrior, 76 Axemen and 29 Elf Lords!
July 7 of YR6 	Meteors rain across the lands and kill 173 peasants, 1 soldier, 2 Warriors, 119 Axemen and 46 Elf Lords!
July 8 of YR6 	Meteors rain across the lands and kill 181 peasants, 1 soldier, 1 Warrior, 82 Axemen and 32 Elf Lords!
July 9 of YR6 	Meteors rain across the lands and kill 82 peasants, 21 Axemen and 8 Elf Lords!

EDIT: Och namnen på enheterna varierar beroende på vilken ras man valt.

Det måste finnas ett mönster, peasants kommer före Warrior och Axemen kommer efter Warrior(?) Man behöver nog veta alla ras namn och sånt för att kunna presentera om datan. Vad jag kan komma på just nu.

Medlem sedan juli 20041 183 inlägg
#5

Jag känner till alla namnen i singular, finnas att läsa på http://wiki.utopia-game.com/index.php/WoL_Races

Mönstret är alltid "peassant, offensive unit, defensive unit, elit unit!" men om en kategori inte har några förluster finns den inte med.

Jag har nästan löst det men warrior ger träff på warriors just nu. Vet inte riktigt om det är ett problem då jag kanske kan köra regexen en gång på warrior.

Medlem sedan juni 20019 519 inlägg
#6
(?:(\d+) peasants?), (?:(\d+) (?:warrior|göran)),

ser du två exemplen, första gruppen kommer hämta ut alla peasant, peasants och grupp 2 kommmer ge värdet på "warrior" och "göran" vid de raser som inte ha alls samma text i plural.

Medlem sedan juli 20041 183 inlägg
#7

ok, men vad händer om warrior eller göran saknas? Om eliter (4e värdet) påverkats står det "and" före. Jag har en lösning på g men den är antagligen krångligare än din :/

(?:(\d+) peasants?), (?:(\d+) (?:warrior|göran)), (?:(\d+) (?:archer|alfons)),
Medlem sedan juni 20014 290 inlägg
#8

fel tänkt igen, kommer kanske med ett bättre förslag senare :)

Medlem sedan juni 20014 290 inlägg
#9

Föreslår att när du loopar igenom filen och plockar ut resp. information för sig.

Förslag i perl:

#!/usr/bin/perl

my $peasants=0;
my $warrior=0;
my $soldier=0;
my $axemen=0;

while (<>) {
        $namn=$1 if /(\w+) rain/;
        $peasants=$peasants+$1 if /(\d+) peasants/i;
        $warrior=$warrior+$1 if /(\d+) warrior/i;
        $soldier=$soldier+$1 if /(\d+) soldier/i;
        $axemen=$axemen+$1 if /(\d+) axemen/i;
}

print "$namn killed $peasants peasants, $warrior warriors, $soldier soldiers, $axemen axemen \n";

Denna perl snutt skriver ut:

Meteors killed 794 peasants, 6 warriors, 2 soldiers, 416 axemen
Medlem sedan juni 20019 519 inlägg
#10

usch, misstag av mig ;)

(?:(\d+) (?:peasants|peasant))?, (?:(\d+) (?:warrior|warriors))?

med ? i varje grupp:

(?:(\d+) peasants?(?:, | and )?)?(?:(\d+) soldier?(?:, | and )?)?(?:(\d+) Warriors?(?:, | and )?)?(?:(\d+) Axemen(?:, | and )?)?(?:(\d+) Elf Lords)?!
Medlem sedan juli 20041 183 inlägg
#11

Ok, nu har jag fått det mesta att fungera men är lite osäker på hur man ska plocka ut data ut följande sträng.

[code]March 9 of YR5 \tForces from Casey (1:11) came through and ravaged our lands! They captured 182 acres! We lost 41 soldiers and 521 Axemen in this battle. We reawakened 281 of our dead troops into soldiers.[code]

Jag vill kunna få ut:
Casey (1:11)
182 acres
41 soldiers
521 Axemen

Truppförlusterna kan variera med olika namn och olika många typer så jag är inne på att bara plocka ut "We lost 41 soldiers and 521 Axemen in this battle." och sen göra vanliga strängoperationer.

Hur gör jag detta på bästa sätt? :)

Medlem sedan juni 20019 519 inlägg
#12

soldarena osv känns som du redan har fått visat, casey kan vara

([^(]+ (\d+:\d+)

Medlem sedan juli 20041 183 inlägg
#13

ok, förlusterna lyckas jag fixa med

(?:(\d+) (?:acres|soldiers|Axemen|Berserkers?))

men lyckas inte få en matchning på namnet. Namnet kan innehålla mellanslag och kan t.ex. se ut såhär:

January 22 of YR7 \tForces from An unknown province from Going to war - stay out (1:24) came through and ravaged our lands! They captured 184 acres! We lost 482 Axemen and 111 Berserkers in this battle. We reawakened 296 of our dead troops into soldiers.

Det är alltså först en tab och slutar med (X:X).

Att jag aldrig kan lära mig regex. Håller på med det för sällan för att tänket ska sätta sig och stanna kvar :/

Medlem sedan juni 20019 519 inlägg
#14

miss av mig:

([^(]+ \(\d+:\d+\))

vill du ju ha för att få match, namnet spelar ingen roll så länge den inte innehåller "(" så är det lugnt.

Medlem sedan juli 20041 183 inlägg
#15

Ok, nu fungerar det mesta rätt så bra. Har dock några små problem kvar. Den ena är att när talen blir större innehåller de kommatecken som tusentals-separator.

Alltså är

March 23 of YR7 1,547,321 horses have been stolen!

egentligen 1547321.

Nu när jag skriver detta kommer jag på att jag kanske ska plocka bort alla kommatecken först, vilket fungerar. Men jag lyckades också modifiera uttrycket så att jag får ut tal, men vet inte riktigt vad den gör, speciellt den senare delen efter |

(?:(\d+\,?\d*\,?\d*|\,\d+)

// istället för

(\d+)

Är det säkert att använda denna eller ska jag plocka bort kommatecknen med en enkel replace?

Medlem sedan juni 20019 519 inlägg
#16

([\d,]+)

om du vill matchar 0-9 och ,

Sen få du köra en replace eller konvertera machningen till ett tal.

271 ms totalt · 4 externa anrop · v20260731065814-full.6fe65c25
127 ms — deklarationer (db)
0 ms — hämta statistik (cache)
141 ms — hämta tråd, inlägg och bilagor (db)
124 ms — ändringar (db)