rimuovere le righe più recenti della data specificata in un file


8

Sono bloccato su come posso fare per eliminare le righe più recenti della data specificata. Ecco un frammento del contenuto di un file.

buildsave.txt

647919 2013/11/30
647946 2013/11/30
647955 2013/12/01
648266 2013/12/03
648267 2013/12/03
648674 2013/12/04

Vorrei rimuovere solo le righe più recenti rispetto al 2013/12/03

647919 2013/11/30
647946 2013/11/30
647955 2013/12/01

Come può essere fatto attraverso bash?

Risposte:


4

Se il tuo sistema include la versione GNU del datecomando, puoi usarlo per convertire il campo della data (dopo aver rimosso il trailing <br>, se presente) in secondi dall'epoca e confrontarlo direttamente con la data di taglio nello stesso formato, ad esempio in bash

testsecs=$(date +%s --date="2013/12/03")
while IFS= read -r line; do
  read -r x d <<< "$line" 
  if (( $(date +%s --date="${d%<br>}") < $testsecs )); then
    printf '%s\n' "$line"
  fi
done < buildsave.txt

[Si noti che ciò non comporta una cancellazione sul posto: è necessario salvare i risultati in un file temporaneo e rinominare.]


Signore, mi ha risparmiato un mal di testa. Questo e 'esattamente quello che stavo cercando!
Jason G,

che schifo! Quelle date ordinano lo stesso lessicograficamente e cronologicamente, non è necessario convertirle in numeri interi ed eseguire 5 comandi, creare un file temporaneo e due pipe per riga!
Stéphane Chazelas,

9

Quelle date ordinano lo stesso lessicograficamente e cronologicamente, quindi è solo una questione di fare un confronto lessicale:

awk '$2 < "2013/12/03"'

2

Presumo che <br>nella tua domanda alla fine della datecolonna sia qualcosa di indesiderato. In ogni caso, può essere rimosso facilmente se è presente. Tuttavia, arrivando alla parte principale puoi ottenere ciò che stai cercando di fare usando,

sort -k 2n filename.txt

Ora, il comando sopra darebbe l'output in modo ordinato. Ora, il comando seguente dovrebbe dare quello che cerchi.

sort -k 2n filename.txt | awk '/2013\/12\/03/ {exit} {print}' 

Spiegazione

Il comando sort ordina sostanzialmente il file in base alla seconda colonna che è la data. Quindi ho modificato il tuo file di input per testare il comando se funziona poiché il file di input ha tutti i dati ordinati per impostazione predefinita. Dopodiché, il awkcomando stampa tutte le linee fino a quando incontriamo una corrispondenza particolare.

analisi

cat filename.txt

647919 2014/01/01
647946 2012/11/30
647955 2011/01/04
648266 2013/12/03
648267 2013/12/03
648674 2013/12/04

Ora, l' sort -k 2n filename.txtoutput è,

647955 2011/01/04
647946 2012/11/30
648266 2013/12/03
648267 2013/12/03
648674 2013/12/04
647919 2014/01/01

Ora siamo soddisfatti del fatto che il file sia ordinato nella seconda colonna. Ora, per selezionare i valori FINO A una data particolare,

sort -k 2n filename.txt | awk '/2013\/12\/03/ {exit} {print}' 

Nell'esempio sopra, ottengo tutti i valori fino a 2013/12/03. L'output è,

647955 2011/01/04
647946 2012/11/30

No, <br>fa parte del mio file

In questo caso, possiamo modificare leggermente il comando come di seguito.

awk '{print $1, substr($2, 1, length($2)-4)}' filename.txt | 
sort -k 2n filename.txt | awk '/2013\/12\/03/ {exit} {print}' 

Quindi sto solo rimuovendo tutti i <br>tag dalla seconda colonna e quindi eseguendo il piping del comando sopra menzionato.

Riferimenti

https://unix.stackexchange.com/a/11323/47538

https://unix.stackexchange.com/a/83069/47538


Grazie per il tuo contributo. questo funziona davvero molto, tuttavia, la condizione per uscire non funziona sempre quando la data specifica non esiste nel file.
Jason G,

no, i tag br sembrano essere aggiunti solo per rendere leggibile la cosa. Non possono essere visti nella prima revisione
Braiam,

-1

Soluzione rapida e sporca per la data che hai dato, basta eliminare tutte le righe con sed, che corrispondono a date successive a questa data:

sed -i "" "#[0-9]* 2013/12/0[4-9]#d" testfile.txt
sed -i "" "#[0-9]* 2013/12/[123][0-9]#d" testfile.txt
sed -i "" "#[0-9]* 2014/[0-9][0-9]/[0-3][0-9]#d" testfile.txt

-I "" si sta sostituendo direttamente all'interno del file e non sta creando un backup, ma è anche possibile reindirizzare testfile attraverso tutti e 3 i comandi sed senza -i "".

A seconda del sistema (linux o mac) è possibile inserire "" dopo -i e talvolta è necessario il parametro -e per le espressioni regolari. Devo provare ciò che funziona per te.

Domanda correlata con ulteriori informazioni su sed: /programming/5410757/


#è il comando comment in sed, quindi quelli non faranno nulla. Utilizzare sed '\#patter#d'se si desidera un delimitatore RE diverso da /. La [0-9]*parte è ridondante senza ^ancora. -eè necessario solo quando si desidera passare diverse espressioni. Linux è un kernel, mac è un marchio di computer, nessuno ha a che fare con sed. La distinzione è tra GNU sede FreeBSD sed(che OS / X (come si trova su alcuni mac) eredita).
Stéphane Chazelas,
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.