eliminar líneas que son más nuevas que la fecha dada en un archivo

8

Estoy atascado en cómo puedo eliminar líneas que son más nuevas que la fecha dada. Aquí hay un fragmento de contenido de un archivo.

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

Me gustaría eliminar las líneas que son más recientes que 2013/12/03 dejando solo

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

¿Cómo se puede hacer esto a través de bash?

Jason G
fuente

Respuestas:

4

Si su sistema incluye la versión GNU del datecomando, puede usarlo para convertir el campo de fecha (después de quitar el final <br>, si está presente) a segundos desde la época y comparar directamente con la fecha de corte en el mismo formato, por ejemplo, en 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

[Tenga en cuenta que esto no realiza una eliminación en el lugar; necesitaría guardar los resultados en un archivo temporal y cambiar el nombre.]

conductor de acero
fuente
Usted señor me ahorró un dolor de cabeza. ¡Esto es exactamente lo que estaba buscando!
Jason G
¡qué asco! Esas fechas se ordenan de la misma manera lexicográfica y cronológicamente, ¡no es necesario convertirlas a enteros y ejecutar 5 comandos, crear un archivo temporal y dos tuberías por línea!
Stéphane Chazelas
9

Esas fechas se clasifican de la misma manera lexicográfica y cronológicamente, por lo que solo es cuestión de hacer una comparación léxica:

awk '$2 < "2013/12/03"'
Stéphane Chazelas
fuente
2

Supongo que <br>en su pregunta al final de la datecolumna es algo no deseado. En cualquier caso, se puede quitar fácilmente si está presente. Sin embargo, al llegar a la parte principal, puede lograr lo que está tratando de hacer usando,

sort -k 2n filename.txt

Ahora, el comando anterior daría la salida de manera ordenada. Ahora, el siguiente comando debería dar lo que busca.

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

Explicación

El comando de clasificación básicamente ordena el archivo en función de la segunda columna, que es la fecha. Así que modifiqué su archivo de entrada para probar el comando si funciona, ya que el archivo de entrada tiene todos los datos ordenados por defecto. Después de eso, el awkcomando imprime todas las líneas hasta que encontremos una coincidencia particular.

Pruebas

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

Ahora, la sort -k 2n filename.txtsalida es,

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

Ahora estamos satisfechos de que el archivo está ordenado en la segunda columna. Ahora, para seleccionar valores HASTA una fecha particular,

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

En el ejemplo anterior, obtengo todos los valores hasta 2013/12/03. La salida es,

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

No, <br>es parte de mi archivo

Si este es el caso, podemos ajustar el comando ligeramente como se muestra a continuación.

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

Así que solo estoy eliminando todas las <br>etiquetas de la segunda columna y luego canalizando el comando mencionado anteriormente.

Referencias

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

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

Ramesh
fuente
Gracias por su aporte. Sin embargo, esto funciona mucho, sin embargo, la condición para salir no siempre funciona cuando la fecha específica no existe en el archivo.
Jason G
no, las etiquetas br parecen agregarse solo para hacer que la cosa sea legible. No se pueden ver en la primera revisión
Braiam
-1

Solución rápida y sucia para la fecha que ha dado, simplemente elimine todas las líneas con sed, que coincidan con fechas posteriores a esta fecha:

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

El "i" "está reemplazando directamente dentro del archivo y no está creando una copia de seguridad, pero también puede canalizar el archivo de prueba a través de los 3 comandos sed sin el" i ".

Dependiendo de su sistema (Linux o Mac), puede omitir el "" después de -i y, a veces, necesita el parámetro -e para las expresiones regulares. Tengo que probar lo que funciona para ti.

Pregunta relacionada con más información sobre sed: /programming/5410757/

toppy
fuente
#es el comando de comentariosed , así que esos no harán nada. Úselo sed '\#patter#d'si desea un delimitador RE diferente de /. La [0-9]*parte es redundante sin un ^ancla. -esolo es necesario cuando quieres pasar varias expresiones. Linux es un kernel, Mac es una marca de computadora, ninguno tiene nada que ver sed. La distinción es entre GNU sedy FreeBSD sed(que OS / X (como se encuentra en algunos Mac) heredó).
Stéphane Chazelas