Hjälp med ett regexp

Tråden skapades och har fått 13 svar. Det senaste inlägget skrevs .
1
  • Medlem
  • Haninge
  • 2007-05-24 20:41

Hej, ny på forumet.

Jag har ett stycke med data som jag ska göra om till användbar xml. Nu är det presenterat på detta sätt:

, 179.000, 44.000, 0.266, -0.158, 0.021, 0.022
, 179.000, 45.000, 0.244, -0.099, 0.031, 0.031
, 179.000, 46.000, -0.156, -0.054, 0.019, 0.019
, 179.000, 47.000, -0.074, -0.074, 0.021, 0.022
, 179.000, 48.000, 0.133, 0.170, 0.019, 0.019
, 179.000, 49.000, 0.070, -0.003, 0.019, 0.020
, 179.000, 50.000, 0.201, -0.120, 0.025, 0.025
, 179.000, 51.000, 0.041, 0.156, 0.021, 0.021
, 179.000, 52.000, 0.232, 0.067, 0.056, 0.036
, 179.000, 53.000, 0.133, -0.097, 0.072, 0.035
, 179.000, 54.000, 0.068, 0.057, 0.046, 0.045

Det jag behöver hjälp med är ett grep-uttryck/regexp/w/e som letar upp det första kommatecknet i varje rad så att jag kan ligga in varje värde i sin egen "<></>".

  • Medlem
  • Kiruna
  • 2007-05-24 20:56

Jag förstår inte riktigt vad du vill åt. Ett RE som hittar första kommatecknet i varje rad ser ut så här:

^[^,]*,

men det hjälper dig knappast nånvart. Vad ska du göra sen? Vilken data ska användas, vilken ska bort och vad ska sättas in?

Posta en snutt indata och önskat resultat utifrån det, så är det lättare att hjälpa dig.

  • Medlem
  • Mölndal
  • 2007-05-24 21:21

Fernet, jag undrar om du verkligen menar vad du skriver...
Vill du bara hitta början på varje rad kan du söka efter \r eller \n (beroende på plattform) med valfri sökfunktion och sedan gå ett tecken framåt.

Vill du gärna använda regex kan du köra t ex "(, [-.\d]*){6}\r" för att få varje värde som en egen capture (dock inklusive komma).

Jag har inte använt grep så mycket för regex, har för mig att den var lite begränsad vad gäller t ex explicit capture och lookahead (därför är förslaget lite förenklat).

Berätta mer exakt vad du är ute efter så kan vi diskutera vidare. Även om jag älskar regex så kan det vara lite långsamt ibland. Om data ser ut exakt som ovan skulle jag nog rekommendera att splitta vid varje komma och sen iterera igenom på vanligt sätt.

Edit: Se där, hade visst inte laddat om sidan på ett tag.

  • Medlem
  • Haninge
  • 2007-05-24 22:42

Oj, Tack för respons och beklagar om jag var lite otydlig. Jag prövar igen

Jag har alltså en fil. Ett oformaterat textdokument bestående av tusentals rader. I varje rad finns sex värden sepererade av kommatecken. Jag vill sortera in dessa värden i xml-noder så att dokumentet blir användbart i en svg-applikation.

Första värdet i varje rad anger en x-koordinat, den andra en y-koordinat. De resterande fyra värdena anger egenskaper hos varje xy-nod.

Så, istället för att datan är presenterad som den nu är, vill jag att det i slutändan ska se ut så här

<node>
<x>179.000</x>
<y>44.000</y>
<value_1>0.266</value_1>
<value_2>0.158</value_2>
<value_3>0.021</value_3>
<value_4>0.022</value_4>
</node>
<node>
<x>179.000</x>
<y>45.000</y>
<value_1>0.244</value_1>
<value_2>0.099</value_2>
<value_3>0.031</value_3>
<value_4>0.031</value_4>
</node>

...istället för som nu:

, 179.000, 44.000, 0.266, -0.158, 0.021, 0.022
, 179.000, 45.000, 0.244, -0.099, 0.031, 0.031

Jag kom fram till att om jag bara kunde ändra det första kommatecknet med i tur och ordning:
Först kör jag ett regexp som ersätter det inledande kommatecknet mot "</node><node><x>" (inga sitationstecken då så klart.)
Då det första kommatecknet nu inte finns kvar så ersätter det andra kommatecknet det första i rollen som första kommatecken. Då skulle jag i en andra regexp ersättning ersätta det nya första kommatecknet med: "</x><y>".
I den tredje regexpersättmingen skulle jag ersätta med: "</Y><value_1>". Så skulle jag fortsätta tills hela dokumentet efter totalt sex regexp-search an replace var fint uppställt i XML-format. Voila.

Jag provade denna som du nämnde spot
^[^,]*,
, men det ville sig inte. Den raderade värdena efter en första lyckad ersättning.

Hoppas det vart lite klarare av vad jag vill åstadkomma. Och så håller vi tummarna på att inte Opera krashar vid postning igen

  • Medlem
  • Haninge
  • 2007-05-24 22:50

...eller när jag tänker efter, varför inte bara göra det ändå enklare och gå från detta:

, 179.000, 44.000, 0.266, -0.158, 0.021, 0.022
, 179.000, 45.000, 0.244, -0.099, 0.031, 0.031

till detta:

komma1 179.000komma2 44.000komma3 0.266komma4 -0.158komma5 0.021komma6 0.022

så är jag säker på att jag klara mig därifrån med en vanlig find and replace

  • Medlem
  • Mölndal
  • 2007-05-24 22:48

Nu är det lite klarare. Jag vet inte riktigt om jag gillar din idé med sök och ersätt direkt i datan (eller en kopia). Det känns mycket renare att parsa ut värdena (med regex eller annat) och sedan konstruera xml-dokumentet på egen hand. De flesta ramverk brukar ha bra stöd för detta i form av metoder AddNode(), AddAttribute() osv.

Provade du mitt förslag? Det var mer av ett tankesätt än en lösning egentligen. Om du dessutom sätter relevanta namn på dina capture groups kan du få riktigt snygg kod i slutändan.

  • Medlem
  • Haninge
  • 2007-05-24 22:55
Ursprungligen av memark:

Nu är det lite klarare. Jag vet inte riktigt om jag gillar din idé med sök och ersätt direkt i datan (eller en kopia). Det känns mycket renare att parsa ut värdena (med regex eller annat) och sedan konstruera xml-dokumentet på egen hand. De flesta ramverk brukar ha bra stöd för detta i form av metoder AddNode(), AddAttribute() osv.

Provade du mitt förslag? Det var mer av ett tankesätt än en lösning egentligen. Om du dessutom sätter relevanta namn på dina capture groups kan du få riktigt snygg kod i slutändan.

Datafilerna är perfekt välformatulerade(!) och reg-exp och annat tjosan är inget jag vill sätta mig in i riktigt. Det är bara ett gäng filer jag måste göra om. En engångsgrej. Ett engångsproblem.

Varför menar du förresten att det skulle vara dåligt att söka och ersätta?

  • Medlem
  • Mölndal
  • 2007-05-24 23:31

Jag skulle inte säga dåligt, snarare "orent". Det handlar väl (som alltid) om hur generell och säker man vill göra sin lösning. Plötsligt om några månader ändras formatet (på data eller på xmlen du ska generera) en smula, och vips får du börja om från början. Delar du istället upp det i steg (parsa, skapa xml) behöver du bara ändra en liten del av koden. Detta är så klart bara tyckande/en känsla från min sida, du är själv bäst lämpad att avgöra vad som passar din situation / din kod.

Säg, visst kan du förstå hur jag tänker när jag tycker att ett mellandataformat av typen
"komma1 179.000komma2 44.000komma3 0.266komma4 -0.158komma5 0.021komma6 0.022" känns ganska kladdigt?

  • Medlem
  • Haninge
  • 2007-05-25 00:06

Memek:

Jo, klart jag förstår det där begreppet med ren och fin kod och ordentliga tillvägagångssätt. Jag instämmer också som regel i det om inte inlärningsbördan blir för stor och slutresultatet inte blir alltför lidande. I kunskaper om regexp är jag ungefär lika kunnig som en gammelmormor. Resultatet blir exakt som jag vill ha det ändå. Ingen ny data kommer att inhämtas senare.

För att klargöra en sak bara; Omvandlingen kommer inte att ske i "runtime" av en applikation utan bar an gång inför skapandet av den.

Så vad tror du, är inte fulvägen ok ändå?

Jag har förresten provat till expression men fårstår absolut int evad jag ska göra :"> Hela texten försvann och ersattes av 63000 "<node>" i en lång rad.

Och Grattis Memek:)

Spot
Det där ser himla vackert ut. Finns det något sätt att använda din kodrad i TextWrangler? Fernet==gammelmormor som sagt

  • Medlem
  • Kiruna
  • 2007-05-24 23:46

OK, då var det lite klarare. Följande awk-snutt löser ditt problem:

awk -F ', ' '{print "<node><x>"$2"</x><y>"$3"</y><value_1>"$4"</value_1><value_2>"$5"</value_2><value_3>"$6"</value_3><value_4>"$7"</value_4></node>"}' indatafil.txt

Flaggan -F sätter fältseparator till ', '
Resten skriver helt enkelt ut respektive kolumn i rätt XML-tagg. Eftersom data inleds med en separator börjar fältena med $2 istället för $1.

Ett alternativ hade varit att rensa upp separatortecknen innan, med hjälp av tr eller sed.

  • Medlem
  • International user
  • 2007-05-25 00:04

Vill du dessutom ha radbrutet mellan taggarna för att göra xml-filen lite mer läsbar kan du klämma in "\n".

efrewrewfefefd

  • Medlem
  • International user
  • 2007-05-25 00:34

Jag skapade en fil som du har med 1 miljon rader. Det tog 5 minuter och 47 sekunder. Den blev 45 MB stor. Jag hann pissa, tvätta mig, borsta tänderna och släcka lamporna. God natt

n=1
while [ $n -lt 1000001 ]
do
echo ', 179.000, 44.000, 0.266, -0.158, 0.021, 0.022' >> data.txt
n=$(($n+1))
done
  • Medlem
  • Mölndal
  • 2007-05-25 11:13

Jag vet inte om det är jag som är Memek och varför du gratulerar mig... men det viktiga är ju att du får en lösning som funkar. Ska det dessutom bara göras en enda gång köper jag ditt fulhack.

Regex är dock kungligt att kunna. Måste rekommendera en fantastisk quickstart / tutorial på
http://www.regular-expressions.info/

1
Bevaka tråden