Nowe posty

xx Dystrybucja pod HP Omen (6)
Wczoraj o 23:30:08
xx [Poradnik] Wyszukiwanie Sterowników (2)
Wczoraj o 21:08:23
lamp Problem z Linux Lite po instalacji (0)
Wczoraj o 19:50:30
xx Ile pingwinów? (1)
Wczoraj o 08:59:24
xx konfiguracja pale moon (0)
2024-03-24, 21:53:42
xx Plasma 6 w Neonie ssie trochę mniej ... (10)
2024-03-23, 02:38:11
xx problem z instalacja sterowników do karty sieciowej (3)
2024-03-18, 18:10:16
xx Plik abc.001 (1)
2024-03-17, 17:48:27
xx Zlecę dopracowanie programu w MatLab (0)
2024-03-13, 15:28:40
xx Linux Mint 21.3 XFCE brak dźwieku po paru minutach (karta muzyczna zintegrowana) (5)
2024-03-12, 23:07:01

Autor Wątek: [Perl] wyciaganie danych z plikow  (Przeczytany 3966 razy)

Gosik

  • Gość
[Perl] wyciaganie danych z plikow
« dnia: 2013-04-21, 20:57:14 »
Witajcie!
 
Mam kilka plikow z danymi i chcialabym z kazdego z nich wyciagnac jedna kolumne.
Co wiecej, te kolumny maja wygladac w nastepujacy sposob:
123  34 55  46
422  24 24  22
332  33 31  33
221  11  1  22
czyli jedna obok drugiej.

W teym celu probuje stworzyc skrypt

my @nazwy;
while (my $nz_pliku = <*.txt>)
{
   push(@nazwy,$nz_pliku);

}
 
my @dane;
foreach my $n(@nazwy){
   open (WYNIKI, "$n");
      while(){
         chomp $_;
               my $k=$_;
               my @kol = split(/ /,$k);
               push (@dane,$kol[4]);                  
       }
     
       
print  "$_ \\n" foreach @dane;
}
close WYNIKI;
Niestety potrafie tylko wyswietlic wyniki w jednej kolumnie. Czy moglabym liczyc na wskazowki, jak z tego wybrnac?

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3049
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
[Perl] wyciaganie danych z plikow
« Odpowiedź #1 dnia: 2013-04-22, 07:06:32 »
:)

Uściślijmy zadanie.

1. Masz kilka plików z kolumnami j/w
2. Z każdego pliku chcesz wyciągnąć JEDNĄ kolumnę.
3. Te kolumny chcesz wstawić do nowego pliku koło siebie.

Np:
P1:
1 2 3
1 2 3
1 2 3

P2:
4 5 6
4 5 6
4 5 6

P3:
7 8 9
7 8 9
7 8 9

I zakładając, że chcesz 2-gie kolumny chcesz dostać:

P:
2 5 8
2 5 8
2 5 8
?
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3049
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
[Perl] wyciaganie danych z plikow
« Odpowiedź #2 dnia: 2013-04-22, 07:33:19 »
Jak tak, to:
$> cat a
a b c
d e f
g h i

$> cat b
1 2 3
4 5 6
7 8 9

$> cat c
A B C
D E F
G H I

$> paste -d" " a b c
a b c 1 2 3 A B C
d e f 4 5 6 D E F
g h i 7 8 9 G H I

$> paste -d" " a b c | sed 's/\\s\\+/ /g' | cut -d" " -f2,5,8
b 2 B
e 5 E
h 8 H
Polecenie paste łączy kilka plików ustawiając je koło siebie w kolumnach. Kolumny oddzielone są tabulatorem albo znakiem podanym w parametrze -d.
Polecenie sed zamienia wielokrotne białe znaki na jedną spację.
Polecenie cut wycina wskazane kolumny oddzielone znakiem wskazanym przez -d.

Jeżeli z góry nie znasz liczby kolumn i plików, to jest drugie rozwiązanie, niestety nie jednolinijkowe:
#!/bin/bash

if [ $# -eq 0 ]; then
        echo "Użycie:"
        echo "$0 NR_KOLUMNY PLIK1 PLIK2 ..."
        exit 255
fi

KOLUMNA=$1
shift

WYJSCIE=""

for F in $@; do
        WY=$(mktemp)
        sed 's/\\s\\+/ /g' "$F" | cut -d" " -f$KOLUMNA > "${WY}"
        WYJSCIE="${WYJSCIE} $WY"
done

paste -d" " $WYJSCIE
rm $WYJSCIE
Użycie (na plikach j/w):
$> ./cutter 1 a b c 
a 1 A
d 4 D
g 7 G
P.S. Sorry, że nie w PERLu, ale zbyt dawno nie używałem :)
-----------
PERL jest jak jazda na rowerze... Szkielet aplikacji wyglądać powinien tak (za stackoverflow):
open FP1,"filename1";
open FP2,"filename2";
my ($l1,$l2);
while(1)
{
  $l1=; chomp $l1;
  $l2=; chomp $l2;
  last unless(defined $l1 or defined $l2);
  print $l1.$l2,"\\n";
}
close FP2;
close FP1;
Twoje potrzebne poprawki to:
1. Obsługa dynamicznej listy plików, zamiast tylko 2. Wystarczy filehandle wpakować w tablicę.
2. Wycinanie konkretnej kolumny z linijki, znowu do tablicy
3. Wywalenie tablicy z p.2 jako linijki do pliku wyjściowego.

Generalnie przy takich zadaniach nie stosuje się metody "zassaj wszystko do pamięci" a "przetwarzaj po jednej linijce ze wszystkich plików naraz". W ten sposób przemielisz pliki, które nie mieszczą się w RAM.
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy