Strona 1 z 2 12 OstatniOstatni
Pokaż wyniki 1 do 10 z 14

Temat: Skrypt przeszukujacy dwa pliki tekstowe i dopisujacy zadane znaki do drugiego pliku

  1. #1

    Exclamation Skrypt przeszukujacy dwa pliki tekstowe i dopisujacy zadane znaki do drugiego pliku

    Czesc
    od kilku dni probuje napisac dosc skomplikowany (jak dla poczatkujacego) skrypt , ktorego zadaniem bedzie przeprowadzanie operacji na dwoch plikach
    a mialo by to wygladac tak:
    operacje są dokonywane na dwóch plikach tekstowych, pierwszy z nich
    jest plikiem tylko do odczytu i wygląda tak :


    1 1 -2.5930E+08 -1.1393E+07 -2.9221E+07 -1.5604E+07 -3.0836E+06 2.6169E+08
    2 1 -1.5113E+08 -5.3081E+06 -6.7720E+07 -7.9690E+06 -7.1801E+06 1.9560E+08
    3 1 -6.1180E+07 -7.6683E+05 -9.4798E+07 -2.5004E+06 -1.0760E+07 1.8449E+08
    4 1 4.4102E+07 9.0110E+06 -7.9293E+07 2.6747E+06 -1.0032E+07 1.4468E+08
    5 1 1.2766E+08 7.3496E+06 -7.5612E+07 8.8286E+06 -1.2019E+07 1.7172E+08
    6 1 3.4349E+08 6.2426E+07 1.6234E+07 2.0982E+07 3.7429E+06 2.4794E+08


    pierwsza liczba w każdej linijce to liczbą porządkową następne to
    parametry, ostatnia to liczna na podstawie której program ma ocenić
    co zrobić z linijka o TYM SAMYM numerze na w drugim pliku tekstowym
    .Drugi plik wygląda tak prawie identycznie jak pierwszy, ma tyle samo
    linijek i 9 kolumn


    1, 93, 297, 20, 1, 1424, 1628, 1351, 1332
    2, 297, 298, 21, 20, 1628, 1629, 1352, 1351
    3, 298, 299, 22, 21, 1629, 1630, 1353, 1352
    4, 299, 300, 23, 22, 1630, 1631, 1354, 1353
    5, 300, 301, 24, 23, 1631, 1632, 1355, 1354
    6, 301, 302, 25, 24, 1632, 1633, 1356, 1355


    Operacja wykonywana przez skrypt ma polegać na odczycie z pierwszego
    pliku liczy porządkowej i porównaniu jej z wcześniej podanym
    parametrem X ( równym np. X=1,2,4,6) jeśli X jest różne od liczby
    porządkowej to należy sprawdzić ostatnia liczbę w linijce i
    porównać ja z Y ( Y ma jedna wartość i jest równe np.
    Y=1.717E+08), jeśli liczba ta jest większa od Y to skrypt powinien
    wprowadzić zmianę w linijce o tym samym numerze w pliku numer dwa -
    zmiana to wstawienie ** na początku linii, tak ze efekt końcowy
    powinien wyglądać tak :
    (plik numer 2)
    1, 93, 297, 20, 1, 1424, 1628, 1351, 1332
    ** 2, 297, 298, 21, 20, 1628, 1629, 1352, 1351
    3, 298, 299, 22, 21, 1629, 1630, 1353, 1352
    4, 299, 300, 23, 22, 1630, 1631, 1354, 1353
    ** 5, 300, 301, 24, 23, 1631, 1632, 1355, 1354
    6, 301, 302, 25, 24, 1632, 1633, 1356, 1355
    plik numer 1 pozostaje niezmieniony
    Wiem ze problem jest skomplikowany(przynajmniej dla mnie), w
    książkach i kursach internetowych nie znalazłem nic co choćby
    przypominało podobny problem .Szukałem tez na forach podobnych
    rozwiązań, niestety bez efektu. Jak do tej pory próbuje
    przekształcić skrypt napisany przez pana Michała Kurka w odpowiedzi
    na mój poprzedni list.
    Czy ktoś byłby w stanie pomoc mi w napisaniu takiego skryptu ?

  2. #2
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie

    Napisać nie problem jak się wie o co chodzi... a zamieszałeś niemiłosiernie :-)

    Cytat Napisał pukas
    pierwsza liczba w każdej linijce to liczbą porządkową następne to
    parametry, ostatnia to liczna na podstawie której program ma ocenić
    co zrobić z linijka o TYM SAMYM numerze na w drugim pliku tekstowym.
    na razie jasne...

    Cytat Napisał pukas
    Drugi plik wygląda tak prawie identycznie jak pierwszy, ma tyle samo
    linijek i 9 kolumn
    [...]
    Operacja wykonywana przez skrypt ma polegać na odczycie z pierwszego
    pliku, liczy porządkowej i porównaniu jej z wcześniej podanym
    parametrem X ( równym np. X=1,2,4,6) jeśli X jest różne od liczby
    porządkowej to należy sprawdzić ostatnia liczbę w linijce i
    porównać ja z Y ( Y ma jedna wartość i jest równe np.
    Y=1.717E+08), jeśli liczba ta jest większa od Y to skrypt powinien
    wprowadzić zmianę w linijce o tym samym numerze w pliku numer dwa -
    zmiana to wstawienie ** na początku linii
    Czyli tłumacząc na bardziej polskawe - tak jak po 20 minutah i piwie to zrozumiałem:

    WEJŚCIE:
    - 2 pliki tekstowe z numerowanymi wierszami (pierwszy 8 kolumn rozdzielanych spacjami, drugi 9 kolumn rozdzielanych przecinkami)
    - parametr X=..... (liczby rozdzielane przecinkami podawane jako ?!? parametry wiersza poleceń, plik o zadanym URL czy jakieś inne cudo?)
    - parametr Y=..... (pojedyncza wartość liczbowa w zapisie wykładniczym - j.w. - skąd program ma to brać?)

    OPERACJE:
    1 - jeśli numer przetwarzanego wiersza w pierwszym pliku nie znajduje się na liście wartości X idź do test 2, inaczej nie rób nic...
    2 - jeśli wartość ostatniej kolumny z pliku pierwszego jest większa od Y to poprzedź linię '** ', inaczej nie rób nic...

    WYJŚCIE:
    - plik tekstowy ze zmienionymi niektórymi liniami... a może nie plik ale po prostu wydrukowanie na ekran i wtedy można to kierować gdzie się chce - plik, pipe, tcp/ip, cokolwiek...

    A tłumacząc to na łopatologię stosowaną... w zmiennej X podajesz numery wierszy które nie mają być sprawdzane tylko od razu zostawione jak są a cała reszta ma być sprawdzana pod kątem wartości ostatniej kolumny (porównanej ze 'stałą' Y).

    Mam rację?!
    Nie rozumiem jeszcze tylko jakim cudem zmieniłeś wiersze 2 i 5 w podanym przykładzie skoro Y=1.717E+08 jest większe od 13xx - jeśli rozjaśnisz ten aspekt i uściślisz to co powyżej to mogę się pobawić... W sumie to jakieś 5-10 minut roboty...

  3. #3

    Unhappy

    ok no wiec to ma wygldac tak :
    WEJŚCIE:
    - 2 pliki tekstowe z numerowanymi wierszami (pierwszy 8 kolumn rozdzielanych spacjami, drugi 9 kolumn rozdzielanych przecinkami)
    - parametr X=..... (liczby podawane wpisywane na poczatku programu, np. z pliku, ja zroblem to tak :
    #wprowadzam zmienne X

    #print 'zaladowalem plik z numerami wezlow';
    open(wezly, 'wezly.txt') || die "brak pliku z wezlami";

    @wezly = <wezly>;
    )

    - parametr Y=..... (podaje ja z klawiatury:
    #wprowadzam druga zeminna Y

    print 'podaj wartosc parametru misessa:';
    $misess =<STDIN>;
    )

    OPERACJE:
    1 - jeśli numer przetwarzanego wiersza w pierwszym pliku nie znajduje się na liście wartości X idź do test 2, inaczej nie rób nic...
    2 - jeśli wartość ostatniej kolumny z pliku pierwszego jest większa od Y to poprzedź ta sama linię w drugim pliku '**' , inaczej nie rób nic...

    WYJŚCIE:
    - plik tekstowy np. OUT.TXT o formacie pliku drugiego (dowolna ilosc wierszy, 8 kolumn) tylko w liniach nie spelniajacych warunkow na paczatku wstawia sie **

    A tłumacząc to na łopatologię stosowaną... w zmiennej X podajesz numery wierszy które nie mają być sprawdzane tylko od razu zostawione jak są a cała reszta ma być sprawdzana pod kątem wartości ostatniej kolumny
    porównanej ze 'stałą' Y).
    zmienna X to sa wyjatki , czyli linie o tych numerach maja nie byc sprawdzane


    Nie rozumiem jeszcze tylko jakim cudem zmieniłeś wiersze 2 i 5 w podanym przykładzie skoro Y=1.717E+08 jest większe od 13xx - jeśli rozjaśnisz ten aspekt i uściślisz to co powyżej to mogę się pobawić... W sumie to jakieś 5-10 minut roboty...
    hmm, no wiec tu chodzi o to ze Y jest wieksze od liczby w 9 kolumnie pierwszego pliku, nie drugiego, drugi plik to poprostu dane do obrobienia , a warunki X i Y sa sprawdzane na 1 pliku i jesli nie sa one spelnione to wtedy 2plik dostaje w odpowiednim wierszu na poczatku '**'

    Jesli umiesz to zrobic albo ktokolwiek umie, to barzo by mi to pomoglo , ja juz kombinuje z tydzien z tym i nie dziala
    Ostatnio edytowane przez pukas : 07-04-2006 - 14:02

  4. #4
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie Gotowe

    No i jak mowilem... dokladnie 11 minut zajelo - uprzedzam jednak, sprawdzane jedynie na podanym wyzej przykladzie...

    Usage: wezly.pl <in-test.txt> <in-modify.txt> <wezly-skip.txt> [Y]

    wezly.pl:
    Kod:
    #!/usr/bin/perl -Tw
    use strict;
    use vars qw/%test %modify $Y/;
    
    # usage
    if ($#ARGV < 2) {
        print "Usage:\n\t wezly.pl <in-tested.txt> <in-changed.txt> <nodes-skip.txt>\n";
        exit 0;
    }
    
    # load data
    if (open (FH, $ARGV[0])) {
        while (<FH>) {
    	chomp;
    	next if (!/^\d/);
    	my @tmp = split(/\s+/);
    	$test{$tmp[0]} = $tmp[$#tmp];
        }
        close (FH);
    } else {
        die "Can't open file $ARGV[0]: $!\n";
    }
    
    if (open (FH, $ARGV[1])) {
        while (<FH>) {
    	chomp;
    	next if (!/^\d/);
    	m/^(\d+)/;
    	$modify{$1} = $_;
        }
        close (FH);
    } else {
        die "Can't open file $ARGV[1]: $!\n";
    }
    
    if (open (FH, $ARGV[2])) {
        while (<FH>) {
    	chomp;
    	next if (!/^\d$/);
    	delete $test{$_};
        }
        close (FH);
    } else {
        die "Can't open file $ARGV[2]: $!\n";
    }
    
    # get Y
    print "Y = ";
    chomp(my $Y=<STDIN>);
    
    # do testing on what has left after loading nodes list
    foreach my $node (keys %test) {
        $test{$node} > $Y ? $modify{$node} = '** ' . $modify{$node} : undef;
    }
    
    # print results to STDOUT (yup! be flexible and redy to be redirected!)
    open (FH, '>wezly-out.txt') || die "Can't open output file: $!\n";
    foreach my $node (sort keys %modify) {
        print FH "$modify{$node}\n";
    }
    close (FH);
    Dane testowe copy'n'paste z tego co podales w opisie. Plik wezly-skip.txt zawiera numery wezlow do pominiecia w testach, jeden numer w kazdej linii (w testach mialem 1, 2, 4 i 6).

    Wynik zapisany do wezly-out.txt to:

    Kod:
    1, 93, 297, 20, 1, 1424, 1628, 1351, 1332
    2, 297, 298, 21, 20, 1628, 1629, 1352, 1351
    ** 3, 298, 299, 22, 21, 1629, 1630, 1353, 1352
    4, 299, 300, 23, 22, 1630, 1631, 1354, 1353
    ** 5, 300, 301, 24, 23, 1631, 1632, 1355, 1354
    6, 301, 302, 25, 24, 1632, 1633, 1356, 1355
    Czyli ok, bo zgodnie z wartosciami wiersz 2 tez powinien byc zmieniony :-)
    Mam nadzieje ze sie przyda :-)

  5. #5

    Smile Dzieki wielkie :-D

    czesc
    widze ze troche w tym siedzisz , jak dla mnie to dosc skomplikowanie wyglda , troche sie zaglebiam ten koda ale niewiele rozumiem
    nie wiem tylko dlaczego u mnie nie dziala to (pisze pod win xp ;perl 5.6.1)
    mozesz mi powiedziec jeszcze tylko jak to zmodyfikowac zeby dzialalo pod xp?
    dostaje wiadomosc : too late for "-T" option at c:\perl\wezly.pl line 1.
    Ostatnio edytowane przez pukas : 07-04-2006 - 18:42

  6. #6
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie

    Po prostu usuń z pierwszej linijki '-T' czyli zostaw 'perl -w' zamiast '-Tw' :-)
    Całe '-T' to nic więcej jak Taint Checking... czsami się przydaje ale skoro Windzie to nie pasuje to po prostu usuń... i tak jest warnings włączone więc czasami jak podłożysz źle sformatowany plik wejściowy to dostaniesz masę informacji typu "Use of uninitialized value at ..." itd. Mówiąc krótko - normalka :-)

    Jeszcze próbowałem właśnie czy nie można poprawić nieco skryptu aby działał w pełni strumieniowo... tzn:

    Kod:
    cat Y.txt test.txt modify.txt exclude.txt |wezly.pl > out.txt
    bo mógłbyś wtedy to puścić jak chcesz i gdzie chcesz :-) ale albo jestem zmęczony albo staram się przekombinować pobawięc się później z ciekawości...

  7. #7

    Domyślnie hmm

    nie wiem , jak usuwam parametr -t lub -tw
    to skrypt konczy dzialanie wyswietlajac tylko:
    Usage:
    wezly.pl<in-tested.txt><in-changed.txt><nodes-skip.txt>

    narazie dalej probuje go uruchomic
    pliki maja formaty:
    in-tested.txt
    1 1 -2.5930E+08 -1.1393E+07 -2.9221E+07 -1.5604E+07 -3.0836E+06 2.6169E+08
    2 1 -1.5113E+08 -5.3081E+06 -6.7720E+07 -7.9690E+06 -7.1801E+06 1.9560E+08
    3 1 -6.1180E+07 -7.6683E+05 -9.4798E+07 -2.5004E+06 -1.0760E+07 1.8449E+08
    4 1 4.4102E+07 9.0110E+06 -7.9293E+07 2.6747E+06 -1.0032E+07 1.4468E+08
    5 1 1.2766E+08 7.3496E+06 -7.5612E+07 8.8286E+06 -1.2019E+07 1.7172E+08
    6 1 3.4349E+08 6.2426E+07 1.6234E+07 2.0982E+07 3.7429E+06 2.4794E+08
    in-changed.txt
    1, 93, 297, 20, 1, 1424, 1628, 1351, 1332
    2, 297, 298, 21, 20, 1628, 1629, 1352, 1351
    3, 298, 299, 22, 21, 1629, 1630, 1353, 1352
    4, 299, 300, 23, 22, 1630, 1631, 1354, 1353
    5, 300, 301, 24, 23, 1631, 1632, 1355, 1354
    6, 301, 302, 25, 24, 1632, 1633, 1356, 1355
    nodes-skip.txt
    1
    2
    4
    6
    Ostatnio edytowane przez pukas : 07-05-2006 - 10:42

  8. #8
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie

    Uzycie:
    Kod:
    wezly.pl <in-tested.txt> <in-changed.txt> <nodes-skip.txt>
    Nie tworzysz tylko plikow... to co jest w nawiasach '<>' to miejsca gdzie masz podac te nazwy... tak jak sie przyjelo - parametry wiersza polecen podane jako '<>' sa obowiazkowe, podane jako '[]' sa opcjonalne, a tutaj opcjonalnych nie ma.

    Jak wywolasz wezly.pl podajac mu dalej w wierszu polecen 3 pelne nazwy plikow z danymi to zadziala :-) zwlaszcza jak po usunieciu -T windows przestal sie buntowac :-)
    Ostatnio edytowane przez TQM : 07-05-2006 - 13:05

  9. #9

    Domyślnie

    ok moj blad, juz wuruchomilem skrypt
    ale co jesli podam w pliku wiele spacji miedzy kolumnami
    in-tested.txt
    1 1 -2.5930E+08 2.7504E+06 -1.1393E+07 -2.9221E+07 -1.5604E+07 -3.0836E+06 2.6169E+08
    2 1 -1.5113E+08 1.2375E+07 -5.3081E+06 -6.7720E+07 -7.9690E+06 -7.1801E+06 1.9560E+08
    3 1 -6.1180E+07 3.2063E+07 -7.6683E+05 -9.4798E+07 -2.5004E+06 -1.0760E+07 1.8449E+08
    4 1 4.4102E+07 5.5269E+07 9.0110E+06 -7.9293E+07 2.6747E+06 -1.0032E+07 1.4468E+08
    5 1 1.2766E+08 9.6003E+07 7.3496E+06 -7.5612E+07 8.8286E+06 -1.2019E+07 1.7172E+08
    6 1 3.4349E+08 1.9436E+08 6.2426E+07 1.6234E+07 2.0982E+07 3.7429E+06 2.4794E+08
    in-changed.txt
    1, 50, 115, 17, 1, 326, 391, 293, 277
    2, 115, 116, 18, 17, 391, 392, 294, 293
    3, 116, 117, 19, 18, 392, 393, 295, 294
    4, 117, 118, 20, 19, 393, 394, 296, 295
    5, 118, 119, 21, 20, 394, 395, 297, 296
    6, 119, 120, 2, 21, 395, 396, 278, 297
    7, 120, 121, 22, 2, 396, 397, 298, 278
    8, 121, 122, 23, 22, 397, 398, 299, 298
    9, 122, 123, 24, 23, 398, 399, 300, 299

    to wtedy dostaje informacjie o bledzie:
    Use of initialized value in concatenation (.) or string at C:\perl\wezly.pl line 53,<STDIN> line 1.

    Wiesz to nie jest hipotetyczny problem, chcialem uzyc tego skryptu do obrobienia pliku tekstowegoo dlugosci kilku tysiecy lini, w zasadzie to dziala ale nie wiem dlaczego daje komunikat o bledzie jesli zmienie format pliku WE

  10. #10
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie

    Zasada dzialania jest prosta:

    1. Sprawdz ilosc parametrow i albo pokaz komunikat o uzyciu albo idz dalej
    2. wczytaj pierwszy plik - tested.txt
    a. jesli linia nie zaczyna sie od cyfry to ja pomin (wiec jak spacja na poczatku to pomin linie)
    b. podziel na pola w miejscu gdzie jest co najmniej jeden znak bialy (spacja/tabulacja)
    c. zapamietaj wartosc z ostatniej kolumny pod 'etykietka' z pierwszej kolumny
    3. wczytaj drugi plik - modify.txt
    a. pomin linie nie zaczynajace sie od cyfry
    b. wez wszystkie cyfry z poczatku linii (az nie trafisz na znak nie bedacy cyfra) i zapamietaj cala linie jak jest pod etykietka tej wlasnie cyfry z poczatku
    4. wczytaj plik nodes-skip.txt
    a. pomin linie nie zaczynajace sie od cyfry
    b. usun z punktu 2 (wartosci do testowania) linie ktora ma ta sama wartosc w 1 kolumnie co wlasnie wczytana wartosc z pliku - ta linia nie bedzie testowana
    5. zapytaj o Y
    6. na tym co pozostalo z danych zebranych w pkt. 2 sprawdzaj czy wartosc ostatniej kolumny jest wieksza od zadanego Y - jesli tak to dodaj '** ' na poczatku linii
    7. dla wszystkich linii wczytanych z drugiego pliku (niektore maja juz '**') zapisz wynik do pliku wyjsciowego zgodnie z numeracja wezlow (rosnaco)...

    Jak sam widzisz mozesz dac wiecej spacji miedzy kolumnami albo zastapic je tabulacjami dla poprawy czytelnosci 'na oko' :-) W tej wersji wazne jest to aby we wszystkich plikach linie zaczynaly sie od cyfr (lub wielocyfrowych liczb calkowitych) i wartosci z pierwszej kolumny byly unikatowe (tzn nie bylo 2 takich samych) i to tyle...

    To co widzisz jako blad to jest wlasnie warning a nie blad - mowi on tyle, ze gdzies (prawdopodobnie we wczytanych danych wejsciowych) byl blad, zostaly one puszczone przez parser i zapamietane jako pusty ciag... doslownie mowiac, zmienna nie ma wartosci.
    Jak usuniesz '-w' z pierwsze linii to tego nigdy wiecej nie zobaczysz ale czasami sie to przydaje do sledzenia dlaczego program nie chodzi... a ten chodzi.

    Pamietaj ze podales dokladny opis formatu danych i tego program sie trzyma... i tak na wyrost jest dzielenie na 1+ spacjach/tabulacjach zamiast na sztywno na pojedynczej spacji :-)

Strona 1 z 2 12 OstatniOstatni

Zasady Postowania

  • Nie możesz zakładać nowych tematów
  • Nie możesz pisać wiadomości
  • Nie możesz dodawać załączników
  • Nie możesz edytować swoich postów
  •  
Subskrybuj