[Perl] parsen van een file met verschillende line endings

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 08-09 14:43
Ik heb een Perl script geschreven dat een file parst.
Als het script een speciale tag tegen komt print ie iets als:
"tag X gevonden op regel Y"

Nou viel me op dat mijn regel nummers er enkele duizenden regels langs zat.
(het zijn vrij grote files)

Nadat ik de file geconverteerd had naar Windows line endings waren de regen nummers goed.

de regelnummers hou ik bij met een simpele counter en met een simpele while loop ik door de file heen.
code:
1
2
3
4
5
open(MYINPUTFILE, 'c:\test.txt');
while(<MYINPUTFILE>)
{
    #keep track of the line numbers
    $line_number ++;


Ik heb gevonden dat je heel de file ineens kan inlezen en dan kan gaan splitten, maar dat vind ik niet zo'n fijn idee gezien de files serieus groot kunnen zijn.

Ook kan je commandline opgeven wat voor soort line endings Perl moet gebruiken, maar ik vermoed dat deze files meerdere soorten (Windows en Linux) door elkaar bevatten.
Ook wil ik het in m'n script oplossen en de caller er niet mee vermoeien.

Hoe kan ik mijn script zowel Linux als Windows line endings laten accepteren?

[ Voor 3% gewijzigd door liquid_ice op 13-07-2012 09:23 ]

Klus page: http://klusthuis.blogspot.com


Acties:
  • 0 Henk 'm!

  • veldsla
  • Registratie: April 2000
  • Laatst online: 10-09 16:26
Ik strip dan altijd alle mogelijke end characters van het einde van de string. Dan wordt het dus zoiets:

Perl:
1
2
3
4
5
6
7
open(MYINPUTFILE, 'c:\test.txt');
while(<MYINPUTFILE>)
{
    s/[\r\n]+$//;
    #keep track of the line numbers
    $line_number ++;
}

Acties:
  • 0 Henk 'm!

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 08-09 14:43
@Veldsla, dit stript alleen de end characters van een 'regel', maar het probleem zit um een stap eerder.

in de while bepaalt Perl ergens wat dat ie een regel noemt, maar dat baseert ie op de verkeerde end characters.

Ik zit dus met 'regels' die eigenlijk in het echt uit meerdere regels bestaat.

Klus page: http://klusthuis.blogspot.com


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:10
Je bedoelt dat in Windows je files met UNIX newlines niet goed gelezen worden?

Misschien helpt het de record separator $/ anders in te stellen? Bijvoorbeeld:
Perl:
1
local $/ = "\n";

Dan krijg je wel weer carriage returns in andere files...

Acties:
  • 0 Henk 'm!

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 08-09 14:43
het toevoegen van:
code:
1
local $/ = "\n";


heeft geen invloed.

Als ik de file in notepad++ bekijk met de optie dat ie alle characters laat zien, dan zie ik:
* Regels die eindigen met CR LF
* Regels die eindigen met LF
* Regels die eindigen met CR

en dat allemaal in 1 file.

Klus page: http://klusthuis.blogspot.com


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Weet je zeker dat je ook CR-line endings (Mac) hebt? Anders <:crlf gebruiken bij het openen.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 08-09 14:43
de CR zie ik BIJNA alleen op lege regels, BIJNA...

Als er een file gecopierd wordt zie ik iets als:
sqlite | 4 kB | 4.0 kB/s | ETA: 00:02:58 | 0% <<CR>>
sqlite | 719 kB | 719.8 kB/s | ETA: 00:00:00 | 100% <<CR>> <<LF>>

dat komt van een commandline af.

Klus page: http://klusthuis.blogspot.com


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
http://search.cpan.org/~audreyt/PerlIO-eol-0.14/eol.pm of "<:crlf:via(AnyCRLF)" in http://www.perlmonks.org/?node_id=813753 anders. Vermoed dat die eerste wat lastiger te installeren is. Als het hele bestand in het geheugen past is het wat makkelijker en kun je ook een regex op het hele bestand doen.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • boe2
  • Registratie: November 2002
  • Niet online

boe2

'-')/

Wat ik doe is puur op lf splitsen en dan in de lijn zelf de eventuele cr wegtrimmen.

'Multiple exclamation marks,' he went on, shaking his head, 'are a sure sign of a diseased mind.' - Pratchett.


Acties:
  • 0 Henk 'm!

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 08-09 14:43
Boeboe schreef op dinsdag 17 juli 2012 @ 13:18:
Wat ik doe is puur op lf splitsen en dan in de lijn zelf de eventuele cr wegtrimmen.
hoe ga je dan om met een file die alleen maar CR heeft?

Ik heb 3 soorten line endings

Klus page: http://klusthuis.blogspot.com


Acties:
  • 0 Henk 'm!

  • boe2
  • Registratie: November 2002
  • Niet online

boe2

'-')/

Lijnen met enkel CR, apart. Ik heb niets gezegd dan :p

'Multiple exclamation marks,' he went on, shaking his head, 'are a sure sign of a diseased mind.' - Pratchett.


Acties:
  • 0 Henk 'm!

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 08-09 14:43
Boeboe schreef op dinsdag 17 juli 2012 @ 13:27:
Lijnen met enkel CR, apart. Ik heb niets gezegd dan :p
Ik heb graag input van mensen die vaker Perl gebruiken, voor mij is het allemaal vrij nieuw.

Klus page: http://klusthuis.blogspot.com


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:10
Ok, het is dus een zootje. Hoe groot zijn die bestanden? Als ze in het geheel in het geheugen passen, kun je 't simpelweg zo oplossen:
Perl:
1
2
3
4
undef $/;
for $line (split /\r\n|\r|\n/, <MYINPUTFILE>) {
  # doe iets met $line
}

Acties:
  • 0 Henk 'm!

  • veldsla
  • Registratie: April 2000
  • Laatst online: 10-09 16:26
liquid_ice schreef op dinsdag 17 juli 2012 @ 13:39:
Ik heb graag input van mensen die vaker Perl gebruiken, voor mij is het allemaal vrij nieuw.
Nou over het algemeen dagelijks, maar er is geen standaard oplossing. Ik ga met soultaker mee, dat is het eenvoudigste. Gaat dit niet dan kun je in een loop met het read commando een buffer vol lezen en daar die regex op toepassen.

Acties:
  • 0 Henk 'm!

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 08-09 14:43
Bedankt, het werkt.

Ik heb alleen deze code moeten aanpassen
code:
1
($arrow, $command, $test_name) = split(" ");

naar
code:
1
($arrow, $command, $test_name) = split(" ", $line);


En de regel verwijderd waar ik $line geed assignen

[ Voor 23% gewijzigd door liquid_ice op 18-07-2012 10:29 ]

Klus page: http://klusthuis.blogspot.com

Pagina: 1