GNU/Linux >> Znalost Linux >  >> Linux

Vyberte řádky z textového souboru, jejichž ID jsou uvedena v jiném souboru?

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

Linux
  1. Efektivně odstranit prvních pár řádků z textového souboru?

  2. Upravit příchozí poštu z textu/prostého na text/html?

  3. Jak odstranit řádky, které se objevují v souboru B, z jiného souboru A?

  1. Odstraňte liché nebo sudé řádky z textového souboru

  2. Odstraňte prvních N řádků z aktivního souboru protokolu

  3. Jak extrahovat text z velkého souboru počínaje prvním výskytem řetězce?

  1. Jak odstranit duplicitní řádky uvnitř textového souboru?

  2. Nahradit řádky odpovídající vzoru řádky z jiného souboru v pořadí?

  3. Jak odstranit více náhodných řádků z textového souboru pomocí Sed?