GNU/Linux >> Linux Esercitazione >  >> Linux

Come rimuovere le linee che appaiono sul file B da un altro file A?

Se i file sono ordinati (sono nel tuo esempio):

comm -23 file1 file2

-23 sopprime le righe che si trovano in entrambi i file o solo nel file 2. Se i file non sono ordinati, reindirizzali attraverso sort prima...

Vedi la pagina man qui


vieni in soccorso!

Questa soluzione non richiede input ordinati. Devi fornire prima il fileB.

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

ritorna

A
C

Come funziona?

NR==FNR{a[$0];next} idiom serve per memorizzare il primo file in un array associativo come chiavi per un successivo test "contiene".

NR==FNR sta controllando se stiamo scansionando il primo file, dove il contatore di righe globale (NR) è uguale al contatore di righe del file corrente (FNR).

a[$0] aggiunge la riga corrente all'array associativo come chiave, nota che questo si comporta come un set, dove non ci saranno valori duplicati (chiavi)

!($0 in a) ora siamo nel prossimo file, in è un test di contiene, qui controlla se la riga corrente è nel set che abbiamo popolato nel primo passaggio dal primo file, ! nega la condizione. Ciò che manca qui è l'azione, che per impostazione predefinita è {print} e di solito non scritto esplicitamente.

Tieni presente che ora può essere utilizzato per rimuovere le parole dalla lista nera.

$ awk '...' badwords allwords > goodwords

con una leggera modifica può pulire più elenchi e creare versioni pulite.

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

Un altro modo per fare la stessa cosa (richiede anche un input ordinato):

join -v 1 fileA fileB

In Bash, se i file non sono preordinati:

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

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

  • funziona su file non ordinati (a differenza di comm )
  • mantiene l'ordine
  • è POSIX

Esempio:

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

cat <<EOF > B
0
1
EOF

grep -Fvxf B A

Uscita:

b
a
01
b

Spiegazione:

  • -F :usa stringhe letterali invece del BRE predefinito
  • -x :considera solo le corrispondenze che corrispondono all'intera riga
  • -v :stampa non corrispondente
  • -f file :prende i modelli dal file specificato

Questo metodo è più lento sui file preordinati rispetto ad altri metodi, poiché è più generale. Se anche la velocità è importante, vedi:Modo rapido per trovare righe in un file che non sono in un altro?

Ecco una rapida automazione bash per il funzionamento in linea:

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 a monte.

utilizzo:

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

Vedi anche:https://unix.stackexchange.com/questions/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-other


Linux
  1. Come spostare i file da un account utente a un altro sullo stesso computer?

  2. Come rimuovo i file dal cestino su Ubuntu?

  3. Come rimuovo le nuove righe da un file di testo?

  4. Come utilizzo le righe di un file come argomenti di un comando?

  5. Come rimuovere X byte dalla fine di un file di grandi dimensioni senza leggere l'intero file?

Come rimuovere la password da un file PDF in Linux

Come decomprimere i file gz in Linux

Come rimuovere le righe da un file usando il comando Sed

Come rimuovere (^M) caratteri da un file in Linux

Come eliminare i file elencati in un altro file in Linux

Come copiare un file da un'altra directory a quella corrente?