Come posso modificare le ultime n righe in un file?


10

Esiste un comando che mi permetterà di modificare le ultime n righe in un file? Ho diversi file, tutti con un diverso numero di righe all'interno. Ma vorrei modificare le ultime n righe in ogni file. L'obiettivo è sostituire le virgole con punti e virgola nelle ultime n righe. Ma solo nelle ultime n righe.

Non voglio eliminare alcuna riga, voglio solo sostituire ogni virgola con un punto e virgola nelle ultime n righe di ciascun file.

Usando il comando sed sono in grado di sostituire l'ultima riga con questo comando. Come descritto qui: Come posso rimuovere il testo sull'ultima riga di un file?

Ma questo mi permette solo di modificare l'ultima riga e non l'ultimo n numero di righe.


1
Semplicemente usando sed '24,$s/,/:/g' filename dov'è 24la linea di partenza`
Valentin Bajrami il

Risposte:


13

Per sostituire le virgole con punti e virgola sulle ultime n righe con ed:

n=3
ed -s input <<< '$-'$((n-1))$',$s/,/;/g\nwq'

Dividendolo a parte:

  • ed -s = eseguito in silenzio (non riportare i byte scritti alla fine)
  • '$-'= dalla fine del file ( $) meno ...
  • $((n-1)) = n-1 righe ...
  • ( $' ... '= cita il resto del comando per proteggerlo dalla shell)
  • ,$s/,/;/g= ... fino alla fine del file ( ,$), cerca e sostituisci tutte le virgole con punti e virgola.
  • \nwq = termina il comando precedente, quindi salva ed esci

Per sostituire le virgole con punti e virgola sulle ultime n righe con sed:

n=3
sed -i "$(( $(wc -l < input) - n + 1)),\$s/,/;/g" input

Rompendo questo a pezzi:

  • -i = modifica il file "sul posto"
  • $(( ... )) = fai un po 'di matematica:
  • $( wc -l < input) = ottieni il numero di righe nel file
  • -n + 1 = torna indietro di n-1 righe
  • ,\$ = da n-1 righe fino alla fine del file:
  • s/,/;/g = sostituisci le virgole con punto e virgola.

Può sostituire wc -l < inputcon wc -l input. Dovrebbe essere più veloce di qualche nanosecondo :)
gardenhead,

1
tranne che wc -l inputgenera anche il nome file; vogliamo solo il conteggio delle righe
Jeff Schaller

Il primo consiglio con ed è eccellente e semplice.
sku2003,

In realtà ho finito per ottenere aiuto da un lato completamente diverso. Ciò ha comportato questo strano pezzo di codice, che fa il trucco ma è lungo e strano. Immagino che queste siano alcune delle cose strane con cui puoi finire quando mettere insieme una soluzione. Comunque il tuo è più carino, più corto e meno complicato del mio: anche qui il codice ha funzionato:
sku2003

cat input.file | sed 's /, /, \ n / g' | sed -n '1! G; h; $ p' | awk -vn = 2 'NR <= n {gsub (",", ";", $ 0)} {print}' | sed -n '1! G; h; $ p' | sed '/ ^ \ s * $ / d'> output.file
sku2003

6

Soluzione che utilizza tac e sed per sostituire ogni virgola con un punto e virgola nelle ultime 50 righe di file.txt:

tac file.txt | sed '1,50s/,/;/g' | tac

5

Con GNU heade una shell tipo Bourne:

n=20
{ head -n -"$n"; tr , ';'; } < file 1<> file

Stiamo sovrascrivendo il file su se stesso. Va bene qui per una traslitterazione da byte a byte, ma non necessariamente se la modifica implica la modifica della dimensione del file (nel qual caso, si vorrebbe sostituire 1<> filecon > other-file && mv other-file filead esempio).


1
Ecco i documenti per i1<> quali non avevo familiarità. Inoltre, spongeda moreutils è un buon strumento per pipeline in cui si desidera sovrascrivere il proprio input.
Miglia,

1

Supponiamo di voler sostituire le ultime 7righe della seguente sequenza con script di shell e implementazione GNU di sed:

$ seq 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Passaggio 1 : consente di ottenere l'ultimo numero di riga della sequenza come il seguente. Dai un'occhiata a questo e quello :

$ lastLine=`seq 20|sed -n '$='`

$ echo $lastLine 
20

Passaggio 2 : consente di impostare il numero di righe (alla fine della sequenza) che intendiamo modificare:

$ numberOfLines=7

$ echo $numberOfLines 
7

Passaggio 3 : consente di calcolare la linea di partenza in base alle variabili precedenti, come il seguente. Dai un'occhiata a questo :

$ startLine=`expr $lastLine - $numberOfLines + 1`

$ echo $startLine 
14

Passaggio 4 : Ora possiamo sostituire le ultime 7 righe di sequenza con qualcos'altro, come il seguente. Dai un'occhiata a questo :

$ seq 20|sed -e "$startLine,+$numberOfLines{s/[12]/WoW/}"
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0

Il passaggio 4 utilizza la sezione 4.4 della pagina man di sed che dice:

'ADDR1,+N'
     Matches ADDR1 and the N lines following ADDR1.

Il passaggio 4 utilizza anche le virgolette doppie come indicato qui .


Bene, i 4 passaggi non sono necessari se utilizziamo la risposta di Gohu in questo modo:

$ seq 20 |tac|sed -e '1,7{s/[12]/WoW/}'|tac
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0

0

Usa taile pipe per sed:

tail -n 20 file | sed 's/,/;/g'

Funziona sul file per le ultime 20 righe. Se vuoi avere le cange direttamente sul file usa:

tail -n 20 file | sed -i 's/,/;/g'

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.