Come copiare selettivamente i dettagli da un file e incollarli in un nuovo file?


11

Ho un file contenente i miei dati personali (.txt). Come posso copiare tramite il terminale solo alcuni dettagli dal file e inserirli in un nuovo .txtfile?

Ad esempio, se questo è il contenuto del file:

name : farah age : 23 phone number : 0123 education : degree

come posso copiare solo l'età e il numero di telefono e inviarli in un nuovo .txtfile?


2
Dipende da cosa vuoi copiare nel nuovo file. Vuoi le prime poche righe, le ultime poche, le righe contenenti una stringa, non contenente una stringa, le linee tra due stringhe? Ci sono strumenti per fare tutto questo, ma dobbiamo sapere cosa desideri fare.
Arcege,

Risposte:


7

Esistono diversi modi per farlo. Se il tuo file ha una struttura nota, puoi usarlo grep. Il grepcomando cerca in un file una frase specifica e restituisce righe che corrispondono a quella frase. Quindi, se il tuo file sembra

Nome: Sally

Data di nascita: 7.31.76

Indirizzo: 1234 Main St.

SSN: 123-45-6789

puoi correre grep Name info.txte tornerà Name: Sally. È quindi possibile reindirizzare l'output su un altro file. Così chiamando

grep Name info.txt > info2.txt

produrrà la riga sul nuovo file info2.txt. Se vuoi aggiungere nuove righe, puoi farlo

grep Address info.txt >> info2.txt

altrimenti il ​​file verrà sovrascritto.

Puoi anche imparare a usare un editor di testo da riga di comando come vim.


2

È possibile utilizzare grep per cercare un'espressione regolare in details.txt e reindirizzare il risultato al nuovo file.

Se tutte le righe che vuoi copiare hanno qualcosa in comune le altre righe non puoi usare:

grep "string in common" details.txt > new.txt

Altrimenti dovrai cercare ogni riga che vuoi copiare, usando ancora grep e aggiungerli a new.txt usando >>al posto di >.


1

Ci sono anche editor che funzionano nel terminale, ad esempio nano, vi ed emacs.

Se si utilizza un'interfaccia utente grafica sul computer locale e un terminale su un computer remoto, è anche possibile utilizzare il mouse per copiare e incollare da una finestra / scheda di terminale a una seconda.


1

Supponendo che il file di input details.txtcontenga:

name: farah
age: 23
phone number: 0123
education: degree

puoi selezionare le righe "name" e "phone" estendendo grep e reindirizzando l'output a new.txt:

grep -E "age:|phone number:" details.txt > new.txt

Questo produrrà new.txt con:

age: 23
phone number: 0123

Come funziona:

Grep stampa solo le linee corrispondenti. Le -Eopzioni abilitate regexp esteso che ti dà la possibilità di usare |(alternativa). Ricorda di citare l'intero modello, quindi |sarà interpretato da grep. Altrimenti la shell tenterà di interpretare. Non lo vuoi qui.


1

Il file che hai mostrato ha tutti i dettagli su una riga:

name : farah age : 23 phone number : 0123 education : degree

Ho ipotizzato che sia possibile inserire un codice age :nel codice ecc. Nel comando, ma il testo che segue varierà e che i dettagli potrebbero non essere nell'ordine dato o essere contigui.

Puoi estrarre parti della linea con grepla -obandiera di. Questo stampa solo la parte abbinata, anziché l'intera linea.

Se si desidera includere le parti age :e phone number :, è possibile utilizzare il -eflag per specificare più corrispondenze oppure alternare.

$ grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file
age : 23
phone number : 0123

L'espressione [^ ]*indica un numero qualsiasi di caratteri che non sono uno spazio, quindi corrisponde ai caratteri dopo age :fino allo spazio successivo.

Sostituisci filecon il nome del file che contiene i tuoi dettagli. È possibile scrivere il nuovo file reindirizzando l'output su un nuovo file con l' >operatore, in questo modo:

grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file > outfile

Quando lo fai, non vedrai alcun output. Dovresti prima controllare l'output, quindi aggiungere il reindirizzamento.

Ecco l'esempio con l'alternanza. Usiamo la -Ebandiera per dire grepdi usare regex esteso. La sintassi è (pattern1|pattern2): questo corrisponde pattern1e / o pattern2. Se viene trovato uno dei due, verrà stampato (indipendentemente dal fatto che l'altro venga trovato o meno). Ora sto usando il +significato di almeno uno del carattere precedente, invece di *indicare zero o più del carattere precedente. In questo contesto, entrambi funzionano ugualmente bene.

$ grep -Eo '(age : [^ ]+|phone number : [^ ]+)' file
age : 23 
phone number : 0123 

Se si desidera omettere le parti age :e phone number:, è possibile utilizzare la -Pbandiera per chiedere grepdi utilizzare espressioni regolari compatibili con Perl. Questo supporta l'alternanza e anche un modo per abbinare il testo dopo un determinato modello:

$ grep -Po '(age : \K[^ ]+|phone number : \K[^ ]+)' file
23
0123

Se si desidera formattare il testo in modo diverso, è possibile utilizzare sed, ad esempio:

$ sed -r 's/.*(age) : ([^ ]*).*(phone number) : ([^ ]*).*/\1:\2 | \3:\4/' file
age:23 | phone number:0123

Questo dipende dal fatto di agevenire prima phone number, quindi aggiusta di conseguenza se non è così. Se non puoi fare affidamento sull'ordine, puoi utilizzare questo comando molto contorto:

$ sed -r 's/(.*)(phone number : [^ ]+)(.*) .*/\2 \1\4/; s/(phone number) : ([^ ]+) .*(age) : ([^ ]+).*/\1: \2 | \3: \4/' file
phone number: 0123 | age: 23

Questo riorganizza la linea in modo che la phone number :sezione venga prima su ogni riga, quindi effettua una seconda sostituzione per selezionare i dettagli desiderati. Devo la tecnica qui usata a questa risposta di Muru .

Note su sedcomandi non coperti da spiegazioni precedenti

  • -rusa regex esteso per comandi più leggibili (GNU sedcapisce -Econ lo stesso significato)
  • s/old/new/sostituire oldconnew
  • (pattern)salva patternin riferimento in seguito, con \1o \2etc (corrispondente all'ordine da sinistra a destra in cui si verificano i gruppi di acquisizione - nota che sedconterrà solo fino a 7 di questi!).
  • .qualsiasi carattere, quindi .*rappresenta un numero qualsiasi di qualsiasi carattere.
  • ; separa i comandi, come nella shell.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.