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.