combinare xargs con sed per modificare o cambiare un file


0

Sto cercando il modello generale *** _ 23 alla fine di una riga (ma non: at_23) all'interno di un file e quindi sto cercando di cambiare tutti questi risultati in \ <23>, nello stesso file di origine ( la funzione di inserimento è sed -i)
Sto facendo:

egrep '[b-s u v w x y z ]+_[0-9]+$' sst_piso_top_c0.spf_typ_C | xargs...

ma tutto il mio tentativo di continuare con sed è fallito.

Qualcuno può spiegare come continuare dopo gli xargs? Come devo consegnare un elenco in sed e dire a sed di elaborare ciascuno nell'elenco e modificarlo sullo stesso file?


la prima soluzione qui è quasi buona. il problema è che * per esempio: * 13 digital_in_13 <- traduci in -> digitale _ \ <31 \> dalla mano non posso cercare solo il _% d% d perché poi troverà anche: at_% d% d che è proibito. forse dovrei aggiungere se statment \
meny

ok. questo è quello che devo fare e la prima risposta di Shevek era vicina: digital_in_31 => digital_in \ <31 \> digital_in_158 => digital_in \ <158 \> blabla_out_112 => blabla_out \ <112 \> spero sia più chiara ora ... :-)
meny

Risposte:


0

Forse non capisco il problema, ma devi solo usarlo sedper quello:

$ sed -ri 's/[b-suvwxyz]+_([0-9]+)$/\\<\1>/g' sst_piso_top_c0.spf_typ_C

Qui stiamo usando ()per acquisire quel valore e quindi \1per stamparlo nella sezione di sostituzione.


0

Non è necessario combinarli egrepe sedpoiché entrambi i comandi cercheranno le corrispondenze all'interno dei file e restituiranno i risultati ( egrep) o agiranno su di essi ( sed), quindi lo sedfarà da solo. Ma per capire perché la tua linea non ha funzionato, andrò con il tuo esempio:

L' egrepoutput regolare ha il modulo filename:matching_linequando viene eseguito su più file e matching_linequando viene eseguito su un singolo file, mentre sedprevede solo nomi di file. Per sopprimere l' egrepoutput normale e stampare solo i nomi dei file che includono corrispondenze, utilizzare l' -lopzione.

Inoltre, non vuoi uno spazio nella tua lista dei personaggi ( [...]), altrimenti sarà troppo avido e corrisponderà a più di una sola parola. Una linea che funzionerebbe è:

$ egrep -l '[b-su-z]+_[0-9]+$' sst_piso_top_c0.spf_typ_C | xargs sed -ri 's/[b-su-z]+_([0-9])+$/\\<\1>/g'

Se un comando composto non funziona, è generalmente una buona idea eseguire da soli i pezzi separati e verificarne i risultati. Inoltre, i messaggi di errore come "Nessun file di questo tipo" indicano di solito la giusta direzione (e sarebbe una buona idea includerli nel rapporto qui).

Infine, come detto sopra, combinando egrepe sednon ha senso. Una linea ragionevole sarebbe

$ sed -ri 's/[b-su-z]+_([0-9])+$/\\<\1>/g' sst_piso_top_c0.spf_typ_C

Aggiornamento: c'era un refuso nel mio regex, che ho corretto. Ho anche incluso il riferimento ai numeri nella partita originariamente incluso da zuazo. Sembra più chiaro dai commenti che hai scritto ora che non vuoi sostituire la corrispondenza completa con un'espressione statica \<23>come l'ho capito per la prima volta, ma vuoi che il numero corrispondente sia visualizzato tra parentesi angolari ...


ma ora ->: * 13 digital_in_13 traduci in digitale _ \ <31 \>
meny

il _in era scomparso
meny

l' in_è scomparso perché corrisponda alla seguente parte l'espressione regolare: [b-su-z]+_. Dalla tua domanda sembrava che questo fosse ciò che volevi. Se stai cercando qualcos'altro, ti preghiamo di specificare più chiaramente - magari usando 2 o 3 righe di esempio - cosa ti piacerebbe abbinare e cosa no.
Shevek,

@meny Aggiungerò una nuova risposta per soddisfare i requisiti che hai descritto nei tuoi ultimi commenti sotto la domanda originale (essendo un nuovo utente posso solo inserire commenti sotto le mie risposte).
Shevek,

0

Ok, per soddisfare i requisiti che hai chiarito nei commenti sotto la tua domanda, dividerei le cose in due parti:

  1. escludere tutte le righe che leggono at_prima del numero finale
  2. dalle righe rimanenti, rimuovere il carattere di sottolineatura alla fine e racchiudere il numero tra parentesi angolari preceduto da una barra rovesciata.

Soluzione per la parte 1 .:

Questo è più facile scrivendo un'espressione regolare che corrisponde esattamente a ciò che non vogliamo e quindi dicendo al comando chiamante di eseguire solo quelle righe che non corrispondono. Questo è fatto più facilmente con grep, quindi usiamolo:

egrep -v "at_[0-9]+" sst_piso_top_c0.spf_typ_C

l' opzione -vo --invert-matchindica grepdi stampare solo linee non corrispondenti.

Soluzione per la parte 2 .:

Questo è più facile con sedil comando s (ubstitute):

sed -r 's/_([0-9]+)$/\\<\1\\>/g'

l'espressione regolare corrisponde al carattere di sottolineatura e un numero alla fine della riga. Racchiudendo la parte numerica tra parentesi (...), possiamo incollarla \1nella sezione di sostituzione. Le sezioni di sostituzione complete sono costituite da parentesi angolari rovesciate che racchiudono il nostro numero di riferimento \\<\1\\>. La barra rovesciata deve essere salvata con un'altra barra rovesciata \\perché altrimenti viene trattata come un carattere di fuga speciale.

Mettere tutto insieme:

Se eseguiamo il pipe dell'output dal egrepcomando in 1. al nostro sedcomando da 2., i sedcomandi lo utilizzeranno come flusso di input:

egrep -v "at_[0-9]+" sst_piso_top_c0.spf_typ_C | sed -r 's/_([0-9]+)$/\\<\1\\>/g' > sst_piso_top_c0.spf_typ_C.new

Normalmente, i sedrisultati vengono inviati all'output standard, quindi la riga sopra li reindirizza a un file ( > newfile). Nota che questo nome file deve essere diverso da quello che egrepsta leggendo, altrimenti sovrascriveremo lo stesso file da cui stiamo leggendo e finiremmo con un file vuoto.


Non dimenticare di votare se trovi utile questa risposta. ;-)
Shevek l'
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.