Používám hodně řazení grep awk v mém unixovém prostředí pro práci se středně velkými (kolem 10-100 milionů řádků) textovými soubory se sloupci oddělenými tabulátory. V tomto ohledu je moje tabulka unixový shell.
Ale mám jeden obrovský problém, a to výběr záznamů podle seznamu ID.
S table.csv
soubor ve formátu idtfootbar...
a ids.csv
soubor se seznamem ID, vyberte pouze záznamy z table.csv
s ID v ids.csv
.
druh https://stackoverflow.com/questions/13732295/extract-all-lines-from-text-file-based-on-a-given-list-of-ids, ale s shellem, ne perl.
grep -F
samozřejmě vytváří falešné poplachy, pokud mají ID proměnnou šířku.join
je nástroj, na který jsem nikdy nemohl přijít. V první řadě to vyžaduje abecední řazení (mé soubory jsou obvykle řazeny číselně), ale ani pak to nedokážu zprovoznit, aniž bych si stěžoval na nesprávné pořadí a přeskakování některých záznamů. Takže se mi to nelíbí.
grep -f proti souboru s ^idt
-s je velmi pomalé, když je počet id velký.awk
je těžkopádný.
Existují pro to nějaká dobrá řešení? Nějaké konkrétní nástroje pro soubory oddělené tabulátory? Mimořádné funkce budou také velmi vítány.
UPD:Opraveno sort
-> join
Přijatá odpověď:
Asi jste mysleli grep -f
ne grep -F
ale ve skutečnosti potřebujete kombinaci obou a -w
:
grep -Fwf ids.csv table.csv
Důvod, proč jste dostávali falešně pozitivní výsledky, je (myslím, že jste to nevysvětlil), protože pokud může být id obsaženo v jiném, vytisknou se obě. -w
odstraní tento problém a -F
zajišťuje, že vaše vzory budou považovány za řetězce, nikoli za regulární výrazy. Z man grep
:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by
newlines, any of which is to be matched. (-F is specified by
POSIX.)
-w, --word-regexp
Select only those lines containing matches that form whole
words. The test is that the matching substring must either be
at the beginning of the line, or preceded by a non-word
constituent character. Similarly, it must be either at the end
of the line or followed by a non-word constituent character.
Word-constituent characters are letters, digits, and the
underscore.
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file
contains zero patterns, and therefore matches nothing. (-f is
specified by POSIX.)
Pokud jsou vaše falešné poplachy způsobeny tím, že ID může být přítomno v poli bez ID, projděte si soubor místo toho:
while read pat; do grep -w "^$pat" table.csv; done < ids.csv
nebo rychleji:
xargs -I {} grep "^{}" table.csv < ids.csv
Osobně bych to udělal v perl
ačkoli:
perl -lane 'BEGIN{open(A,"ids.csv"); while(<A>){chomp; $k{$_}++}}
print $_ if defined($k{$F[0]}); ' table.csv