Mam dwa pliki o różnej długości, ale zarówno z kolumnami rozdzielanymi 3 kartami. Liczba linii do pliku2 wynosi 5 000 000 000 i liczba linii w pliku1 wynosi 2 000 000:

Plik1:

abc foo bar
lmn potato rst
lmp tomato  asd

Plik2:

123 asdasc  dad
032 foo 2134
123 linkin  9123
42  cads    asd
45654   tomato  12123

Muszę użyć drugiej kolumny jako klucza do dopasowania dwóch plików i wyodrębnić linie z pliku1 i pliku2, jeśli jest mecz na drugiej kolumnie

fout = open('outfile', 'w')
with open('file1', 'r') as f1, open('file2', 'r') as f2:
  file2_keys = [i.split('\t')[1] for i in f2]
  for line in f1:
    if line.split('\t')[1] in file2_keys:
      print>>fout, line

Ale to daje mi tylko linię z pliku1.

Pożądane wyjście powinno być

Outfile2:

032 foo 2134
45654   tomato  12123

Outfile1:

abc foo bar
lmp tomato  asd

Czy jest jakiś sposób, aby zrobić to skutecznie w Unix? Jak inaczej może to zrobić skutecznie?

1
alvas 15 sierpień 2014, 12:14

3 odpowiedzi

Najlepsza odpowiedź

Czy jest jakiś sposób, aby skutecznie to zrobić w Unikniku?

Możesz użyć awk.

awk 'NR==FNR{a[$2]=$2;next}{if ($2 in a) {print $0}}' File1 File2

Wytworzy żądany wyjście z File1:

032 foo 2134
45654   tomato 12123

Podobnie,

awk 'NR==FNR{a[$2]=$2;next}{if ($2 in a) {print $0}}' File2 File1

Wytworzy żądany wyjście z File2:

abc foo bar
lmp tomato  asd
5
0xdeadbeef 15 sierpień 2014, 08:31

Efektywnie? Użyj awk jako 0xDeadbeef sugeruje lub trzymać się C ++:

#include <iostream>
#include <fstream>
#include <set>

int main() {

    std::string a, b, c;
    std::set<std::string> s;

    std::ifstream file1("File1");
    while (file1 >> a >> b >> c)
        s.insert(b);

    std::ifstream file2("File2");
    while (file2 >> a >> b >> c)
        if (s.count(b) != 0)
            std::cout << a << "\t" << b << "\t" << c << std::endl;

}

Wyjście

032 foo 2134
45654   tomato  12123
2
enrico.bacis 15 sierpień 2014, 08:43

Ponieważ dodałeś znacznik Pythona i próbowałeś w Pythonie, oto realizacja Pythona:

fout1 = open('outfile1', 'w')
fout2 = open('outfile2', 'w')
with open('file1') as f1, open('file2') as f2:
    file2_lines = [i.strip() for i in f2]
    file2_keys = [i.split(' ')[1] for i in file2_lines]
    d = dict(zip(file2_keys, file2_lines))
    for line in f1:
        k = line.split(' ')[1]
        if k in d:
            print >>fout1, line.strip()
            print >>fout2, d[k]
fout1.close()
fout2.close()
2
WKPlus 15 sierpień 2014, 09:00