Avatar billede cybershah Nybegynder
21. maj 2012 - 22:04 Der er 11 kommentarer og
1 løsning

Forståelse af perl kode

Hej Perl Eksperter

Jeg sidder med et stykke perl script, som jeg ikke helt forstår. (Jeg er ikke nogen haj i området.)

Scriptet skal læse en importeret fil og tælle op hvor mange ;" og "; der er og så lave en sammenligning.

Det er dette stykke af koden, som jeg ikke forstår:

$input_scalar=join("",@input_array);
$countLeft = () = $input_scalar =~ /;\"/g;
$countRight = () = $input_scalar =~ /\";/g;

Nogen der kan hjælpe med den detaljeret beskrivelse??
Avatar billede erikjacobsen Ekspert
21. maj 2012 - 22:13 #1
Linien med join samler alle elementer (linier formentlig) i arrayet @input_array til een lang streng uden linieskift.

Idiomet brugt i de to næste linier er forklaret her

  http://www.perlmonks.org/?node_id=527973

hvor man sætter pattern match til list-mode, og derefter henter længden ud som et tal (skalar).

...<3 perl...
Avatar billede cybershah Nybegynder
22. maj 2012 - 00:54 #2
tak. Det hjalp en del til forståelsen... smid et svar for at få points :)
Avatar billede erikjacobsen Ekspert
22. maj 2012 - 11:04 #3
Jeg samler slet ikke på point, tak. Svar selv, og accepter dit eget svar.
Avatar billede cybershah Nybegynder
24. maj 2012 - 11:43 #4
nå ok, nu giver dit navn mening :) jamen tak så.
Jeg har faktisk en anden udfordring, som har brug for lidt hjælp til. Er jo ret ny til Perl, så har ikke rigtig haft held med at finde de rigtige referencer for lignende problem.

Hvis jeg har en tekst fil med fx dette indhold:

[ Hejabcdedfj"123456",mn,fdljglf;"abcdef"kfmfgmd ]

Hvordan kan jeg printe de tegn der er ind i citationstegnene, altså 123456 og abcdef

På forhånd tak.
Avatar billede erikjacobsen Ekspert
24. maj 2012 - 12:03 #5
Sådan lige ud af landevejen kan du:

$a='[ Hejabcdedfj"123456",mn,fdljglf;"abcdef"kfmfgmd ]';

print "$a\n";
while ($a=~/"(.*?)"/g) {
  print "$1\n";
}
Avatar billede cybershah Nybegynder
24. maj 2012 - 16:07 #6
super tak :) synes jeg bliver mere og mere glad for Perl..

Hvis du har links til tutorials eller guides, som du anbefaler til nybegyndere, må du meget gerne sende.

Mange tak.
Avatar billede erikjacobsen Ekspert
25. maj 2012 - 09:53 #7
Øh, nej, jeg har ikke rigtig fulgt med i hvad der findes af litteratur. Jeg kigger af og til på
  http://pleac.sourceforge.net/pleac_perl/index.html
for inspiration, men man skal li'som vide noget om det på forhånd.

I Perl kan man gøre ting på mange måder. Dit problem kunne også løses med
  @b=$a=~/"(.*?)"/g;
der laver et array, @b, med de matchende strenge. Så kan man bruge @b til udskrift eller andet, fx:
  print join(" - ",@b);
Avatar billede cybershah Nybegynder
25. maj 2012 - 12:01 #8
Tak for det. Løsningen til hele mit problem afhænger meget af Regex og Idiomer, så derfor vil jeg meget gerne have noget dokumentation der forklarer med eksempler osv. For (som nybegynder) det er ret svært synes jeg.

Men kernen er at jeg skal have fanget de karakter, som er inden for citationstegnene og hvis der er en semikolon lige efter eller lige før situationstegnet, skal de skilles med et space.

Altså fx
"abcdef;" og ";1234" skal ændrest til "abcdef; " og " ;1234"

Indtil videre fanger jeg alle strings der er i mellem to " " og smider dem i en tekst fil. Men jeg ved ikke om jeg har valgt en rigtig strategi...
Her er det styk fra koden so far:

my @files = glob("c:/TMP/test/test_*.csv");

foreach $file (@files){ 
open(INPUT,$file) or die; 
@input_array=<INPUT>;
close(INPUT);
   
$input_scalar = join("",@input_array);
   
open (OUTPUT, ">>c:/TMP/test/insideQuotationmark.txt");
print OUTPUT "\nFile name:\n".$file."\n\n";
close(OUTPUT);
   
### printing the characters inside " " (if any)   

while($input_scalar =~ /"(.*?)"/g) {
  $a = $1."\n";       
  open (OUTPUT, ">>c:/TMP/test/insideQuotationmark.txt");   
  print OUTPUT $a;
  close(OUTPUT);
}
}
Avatar billede erikjacobsen Ekspert
25. maj 2012 - 15:17 #9
Du børe nøjes med at åbne OUTPUT een gang, og tilsvarende lukke den een gang til sidst.

Men forstår jeg det korrekt, at det der mangler er at tilføje et mellemrum forrest og bagerst, når der står semikolon?
Avatar billede cybershah Nybegynder
25. maj 2012 - 16:32 #10
Jeg har faktisk fået løst det med at tilføje mellemrum :-)

Det er en txt fil hvor nogle steder er der en række værdier ind i " ". Her må en semikolon ikke stå først eller sidst, så derfor skal der være mellemrum, dvs.
dette ";xyz" skulle gerne ændres til " ;xyz"

Jeg har løst det vha. subrsting, men nu knokler jeg med at skrive tilbage til original filen.

altså
1- jeg læser først fra minFil.txt
2- henter alle de strenge der er i mellem " "
3- tjekker for "; og ;" og tilføjer space i mellem
4- så skal lige præcis det der er ændret skrives tilbage i filen

Det er nr. 4 operation som jeg ikke kan komme videre med. Kan ikke lige se hvordan jeg kan smide de korrekte værdier tilbage i den samme fil igen uden at ændre andet.

koden til substring delen:

foreach $file (@files) 
{       

### opens each trade_import file and puts them in an array   
   
open(INPUT,$file) or die; 
@input_array=<INPUT>;
close(INPUT);
   
$input_scalar = join("",@input_array);
   
open (OUTPUT, ">>c:/TMP/test/insideQuotationmark.txt");
print OUTPUT "\nFile name:\n".$file."\n\n";
       
### printing the characters inside " " (if any)   

while($input_scalar =~ /"(.*?)"/g) {

$freeText = $1;       
       
### determining the first and the last character
       
$lastChar = substr ($freeText, -1,1);   
$firstChar = substr ($freeText, 0,1);
   
### if the first or last character is ; a space will be added
       
if($lastChar =~ /;/g){
           
print "\n--problems with: ".$freeText." in file ".$file."\n";
$correction = substr ($freeText, -1,1,"; ");
print "correction: "."\"".$freeText."\""."\n";   
                   
}
if($firstChar =~ /;/g){
       
print "\n--problems with: ".$freeText." in file ".$file."\n";
$correction = substr ($freeText, 0,1," ;");
print "correction: "."\"".$freeText."\""."\n";
           
}
       
print OUTPUT $freeText;
       
       
}
Avatar billede erikjacobsen Ekspert
25. maj 2012 - 19:03 #11
Ja, og det vil man nok bruge regulære udtryk til - i stedet for explicitte if-er og replaces. Noget i retning af (utestet):

  $freeText=~s/^;/ ;/;
  $freeText=~s/;$/; /;

^ betyder begyndelsen af strengen
$ betyder slutningen af strengen

(PS: Hvor i verden får man et job, hvor man kan bruge Perl. Jeg er en lille smule misundelig...)
Avatar billede cybershah Nybegynder
27. maj 2012 - 23:46 #12
tak for tippet...

det er ingen job, men et learn-by-doing projekt. Men Perl er helt sikkert et spændende sprog.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester