GNU/Linux >> Znalost Linux >  >> Linux

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

Pokud jsou soubory seřazeny (jsou ve vašem příkladu):

comm -23 file1 file2

-23 potlačí řádky, které jsou v obou souborech, nebo pouze v souboru 2. Pokud soubory nejsou seřazeny, propojte je přes sort první...

Viz manuálovou stránku zde


awk na záchranu!

Toto řešení nevyžaduje tříděné vstupy. Nejprve musíte poskytnout soubor B.

awk 'NR==FNR{a[$0];next} !($0 in a)' fileB fileA

vrací

A
C

Jak to funguje?

NR==FNR{a[$0];next} idiom je pro uložení prvního souboru v asociativním poli jako klíče pro pozdější test "obsahuje".

NR==FNR kontroluje, zda skenujeme první soubor, kde se globální počítadlo řádků (NR) rovná aktuálnímu počítadlu řádků souboru (FNR).

a[$0] přidá aktuální řádek do asociativního pole jako klíč, všimněte si, že se to chová jako sada, kde nebudou žádné duplicitní hodnoty (klíče)

!($0 in a) nyní jsme v dalším souboru (souborech), in je test obsahuje, zde se kontroluje, zda je aktuální řádek v sadě, kterou jsme naplnili v prvním kroku z prvního souboru, ! neguje podmínku. Co zde chybí, je akce, která je ve výchozím nastavení {print} a obvykle nejsou psány explicitně.

Všimněte si, že toto lze nyní použít k odstranění slov z černé listiny.

$ awk '...' badwords allwords > goodwords

s malou změnou může vyčistit více seznamů a vytvořit vyčištěné verze.

$ awk 'NR==FNR{a[$0];next} !($0 in a){print > FILENAME".clean"}' bad file1 file2 file3 ...

Další způsob, jak udělat totéž (také vyžaduje seřazený vstup):

join -v 1 fileA fileB

V Bash, pokud soubory nejsou předtříděné:

join -v 1 <(sort fileA) <(sort fileB)

grep -Fvxf <lines-to-remove> <all-lines>

  • funguje na netříděných souborech (na rozdíl od comm )
  • udržuje objednávku
  • je POSIX

Příklad:

cat <<EOF > A
b
1
a
0
01
b
1
EOF

cat <<EOF > B
0
1
EOF

grep -Fvxf B A

Výstup:

b
a
01
b

Vysvětlení:

  • -F :místo výchozího BRE
  • použijte doslovné řetězce
  • -x :zohledňují pouze shody, které odpovídají celému řádku
  • -v :tisk neodpovídající
  • -f file :převzít vzory z daného souboru

Tato metoda je pomalejší u předem setříděných souborů než jiné metody, protože je obecnější. Pokud záleží také na rychlosti, viz:Rychlý způsob hledání řádků v jednom souboru, které nejsou v jiném?

Zde je rychlá automatizace bash pro in-line provoz:

remove-lines() (
  remove_lines="$1"
  all_lines="$2"
  tmp_file="$(mktemp)"
  grep -Fvxf "$remove_lines" "$all_lines" > "$tmp_file"
  mv "$tmp_file" "$all_lines"
)

GitHub upstream.

použití:

remove-lines lines-to-remove remove-from-this-file

Viz také:https://unix.stackexchange.com/questions/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another


Linux
  1. Jak odstranit prázdné řádky ze souboru (včetně tabulátoru a mezer)?

  2. Jak odstranit Bom ze souboru UTF-8?

  3. Jak odstraním soubory z koše na Ubuntu?

  1. Jak odstranit X bajtů z konce velkého souboru bez přečtení celého souboru?

  2. Jak zkopírovat 10 posledních souborů z jednoho adresáře do druhého?

  3. Jak použít sed k odstranění posledních n řádků souboru

  1. Jak přesunout soubory z jednoho uživatelského účtu do druhého na stejném počítači?

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

  3. Jak odeberu zařízení mezipaměti z bcache?