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