[Perl] Variables en escape codes in text file?

Pagina: 1
Acties:

  • muba
  • Registratie: April 2002
  • Laatst online: 19-10-2013

muba

Prince of Persia!

Topicstarter
Stel ik heb dit file:
code:
1
2
3
Hallo dit is een textfile \n en dit is regel2,
hoewel de teksts nog steeds op regel 1 stond.
Hier staat een variable: $myvar.

Nou wil ik dus dat de escape codes automatisch goed geinterpreteerd worden. Als ik dit file namelijk inlees en print, dan staat er gewoon letterlijk "\n". Hoe zorg ik ervoor dat het een echte newline wordt?
Maar dan niet alleen voor \n, maar ook \t, \r, \024 (alle nummers dus) en eigenlijk gewoon allemaal.

En, iets minder belangrijk, maar toch: hoe kun je automatisch variablen laten vervangen?

Alvast bedankt,

[bericht aangepast om horizontale scrollbar te nuken]

Reporter: Mister Gandhi, what do you think of western civilisation?
Gandhi: I think it would be a good idea


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
het is dus geen echte newline.
in php zou ik zoiets doen:
PHP:
1
<?str_replace('\\n', '\n', $text);?>

kan je vast wel wat mee

  • muba
  • Registratie: April 2002
  • Laatst online: 19-10-2013

muba

Prince of Persia!

Topicstarter
Jah, zoiets kan in Perl ook wel, maar wat is nou het probleem: *alle* escape codes moeten worden aangepast, dus ook \024, \213, \004 en noem maar op... Da's dus een beetje heeeeel veel werk. Is er geen makkelijkere methode?

Reporter: Mister Gandhi, what do you think of western civilisation?
Gandhi: I think it would be a good idea


  • Erik Jan
  • Registratie: Juni 1999
  • Niet online

Erik Jan

Langzaam en zeker

Dirty dan maar?
code:
1
eval("print \"$tekst\";"); #Let wel ff op dat quotes geen problemen geven;

This can no longer be ignored.


  • elnino
  • Registratie: Augustus 2001
  • Laatst online: 03-09 05:13
Eval (=evil) kan inderdaad een oplossing zijn, maar kan ook een beveiligingslek vormen. Pas er dus mee op!

Daarnaast zou je ook regular expressions kunnen gebruiken, of het allemaal handmatig vervangen (maar dat is af te raden, nogal veel werk en niet echt flexibel).

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 09-09 11:02
Ik ben geen Perl expert, maar met een reguliere expressie moet je een eind komen:
code:
1
2
3
4
5
6
7
  sub functie
  {
    ..
  }


  $tekst=~s/\\([0-9]{1,3}|[rnt])/functie($1)/eg;

Zie voor details de Perl documentatie over reguliere expressies (perlre), operators (perlop) en functies (perlfunc).

  • tomato
  • Registratie: November 1999
  • Niet online
Als het alleen gaat om wat je hier zegt kun je dat inderdaad gemakkelijk met een s/re//e doen, zie de \n, \t, \r, etcetera apart (zijn er niet zoveel) en voor de nummers kun je vast een functie vinden.

Voor de mensen die wel eens een eval gebruiken, kijk eens naar Safe ('%perldoc safe'), hoewel dat ook niet zaligmakend is ;)

  • muba
  • Registratie: April 2002
  • Laatst online: 19-10-2013

muba

Prince of Persia!

Topicstarter
Heel erg bedankt voor de reacties. Uiteindelijk heb ik het moeten oplossen met een eval. Daar ben ik niet zo heel blij mee. Het werkt wel, maar, zoals jullie zeiden, het brengt wat veiligheidsissues met zich mee.

Wat was nou het probleem met de regexp? De waarde die naar de sub werd doorgegeven, was gewoon simpelweg de letter van de escape code (dus "n", "t", "f", "b" etc...), dat is dus wel goed. Mijn sub zag er zo uit:
code:
1
2
3
4
sub escape {
  my ($esc) = @_;
  return "\\$esc";
}

Want ik dacht, dat zet dus een "\" voor de letter. Als dit dan uiteindelijk weer uitgeprint wordt, dan is het goed.

Maar dat was niet zo! Weer werdt er letterlijk "\n", of "\t" neergezet en NIET een echte newline of tab of...

Kan iemand me nog wat verder opweg helpen?

Reporter: Mister Gandhi, what do you think of western civilisation?
Gandhi: I think it would be a good idea


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 09-09 11:02
Je zal twee gevallen moeten afhandelen: ten eerst het vervangen van letters en ten tweede het vervangen van octale getallen. Het is het makkelijkst om dan ook twee reguliere expressies op je string los te laten (al is dat niet het meest efficient). De subroutine voor de letters wordt dan zoiets:
code:
1
2
3
  my ($letter) = @_;
  $letter =~ tr/ntb/\n\t\b/;
  return $letter;

Dan moet je dus alleen een letter doorgeven (zonder \ ervoor) anders gaat 't mis.

Octale getallen kun je op zo'n manier wel omzetten:
code:
1
2
  $octaal='123';
  $decimaal=($octaal%10)*8+(($octaal/10)%10)*(8*8)+($octaal/100)*(8*8*8);

Deze laatste code kun je in principe ook zonder subroutine implementeren. Het kan zijn dat je tussendoor nog wat naar integers moet casten, maar waarschijnlijk kom je daar zelf wel uit.

Alle code is ongetest! Succes ermee.
Pagina: 1