¿Hay alguna manera de head
/ tail
un documento y obtener la salida inversa; porque no sabes cuántas líneas hay en un documento?
Es decir, solo quiero obtener todo menos las 2 primeras líneas foo.txt
para agregar a otro documento.
fuente
¿Hay alguna manera de head
/ tail
un documento y obtener la salida inversa; porque no sabes cuántas líneas hay en un documento?
Es decir, solo quiero obtener todo menos las 2 primeras líneas foo.txt
para agregar a otro documento.
Puede usar esto para quitar las dos primeras líneas:
tail -n +3 foo.txt
y esto para quitar las dos últimas líneas:
head -n -2 foo.txt
(suponiendo que el archivo termine con \n
el último)
Al igual que para el uso estándar de tail
y head
estas operaciones no son destructivas. Úselo >out.txt
si desea redirigir la salida a algún archivo nuevo:
tail -n +3 foo.txt >out.txt
En el caso de que out.txt
ya exista, sobrescribirá este archivo. Use en >>out.txt
lugar de >out.txt
si prefiere que se agregue la salida out.txt
.
Si desea todas menos las primeras líneas N-1, llame tail
con el número de líneas +N
. (El número es el número de la primera línea que desea conservar, comenzando en 1, es decir, +1 significa comenzar en la parte superior, +2 significa omitir una línea y así sucesivamente).
tail -n +3 foo.txt >>other-document
No hay una forma fácil y portátil de omitir las últimas N líneas. GNU head
permite head -n +N
como contrapartida de tail -n +N
. De lo contrario, si tiene tac
(por ejemplo, GNU o Busybox), puede combinarlo con tail:
tac | tail -n +3 | tac
Portablemente, puede usar un filtro awk (no probado):
awk -vskip=2 '{
lines[NR] = $0;
if (NR > skip) print lines[NR-skip];
delete lines[NR-skip];
}'
Si desea eliminar las últimas líneas de un archivo grande, puede determinar el desplazamiento de bytes de la pieza a truncar y luego realizar el truncamiento con dd
.
total=$(wc -c < /file/to/truncate)
chop=$(tail -n 42 /file/to/truncate | wc -c)
dd if=/dev/null of=/file/to/truncate seek=1 bs="$((total-chop))"
No puede truncar un archivo en su lugar al principio, aunque si necesita eliminar las primeras líneas de un archivo enorme, puede mover el contenido .
Desde la tail
página del manual (GNU tail
, es decir):
-n, --lines=K
output the last K lines, instead of the last 10; or use -n +K to
output lines starting with the Kth
Por lo tanto, lo siguiente debería agregar todas menos las 2 primeras líneas de somefile.txt
a anotherfile.txt
:
tail --lines=+3 somefile.txt >> anotherfile.txt
Para eliminar las primeras n líneas, se puede utilizar GNU sed. Por ejemplo si n = 2
sed -n '1,2!p' input-file
La !
media "excluye este intervalo". Como puede imaginar, se pueden obtener resultados más complicados, por ejemplo
sed -n '3,5p;7p'
eso mostrará la línea 3,4,5,7. Más poder proviene del uso de expresiones regulares en lugar de direcciones.
La limitación es que los números de las líneas deben conocerse de antemano.
sed 1,2d
? Más simple es generalmente mejor. Además, nada en sus ejemplos es específico de GNU Sed; todos sus comandos usan las características POSIX estándar de Sed .
Puede usar diff
para comparar la salida de head
/ tail
con el archivo original y luego eliminar lo que es lo mismo, por lo tanto, obtener el inverso.
diff --unchanged-group-format='' foo.txt <(head -2 foo.txt)
Mientras tail -n +4
que el archivo de salida que comienza en la cuarta línea (todas menos las primeras 3 líneas) es estándar y portátil, su head
contraparte ( head -n -3
todas menos las últimas 3 líneas) no lo es.
Portablemente, harías:
sed '$d' | sed '$d' | sed '$d'
O:
sed -ne :1 -e '1,3{N;b1' -e '}' -e 'P;N;D'
(Tenga en cuenta que en algunos sistemas donde sed
tiene un espacio de patrón de tamaño limitado, que no escala a valores grandes de n
).
O:
awk 'NR>3 {print l[NR%3]}; {l[NR%3]=$0}'
{ head -n2 >/dev/null
cat >> other_document
} <infile
Si se <infile
trata de un lseek()
archivo normal y habilitable, sí, por supuesto, siéntase libre. Lo anterior es una construcción totalmente compatible con POSIX.
Mi enfoque es similar al de Gilles, pero en cambio solo invierto el archivo con cat y canalizo eso con el comando head.
tac -r thefile.txt | head thisfile.txt (reemplaza archivos)
Espero haber entendido claramente tu necesidad.
Tiene varias formas de completar su solicitud:
tail -n$(expr $(cat /etc/passwd|wc -l) - 2) /etc/passwd
Donde / etc / passwd es su archivo
La segunda solución puede ser útil si tiene un archivo enorme:
my1stline=$(head -n1 /etc/passwd)
my2ndline=$(head -n2 /etc/passwd|grep -v "$my1stline")
cat /etc/passwd |grep -Ev "$my1stline|$my2ndline"
Solución para BSD (macOS):
Eliminar las primeras 2 líneas:
tail -n $( echo "$(cat foo.txt | wc -l)-2" | bc )
Eliminar las últimas 2 líneas:
head -n $( echo "$(cat foo.txt | wc -l)-2" | bc )
... no es muy elegante pero hace el trabajo!
\n
" .. Funciona para todos los enteros negativos distintos de los-n -0
cuales no devuelve nada , tal como lo-n 0
haría (usando: head (GNU coreutils) 7.4) ... Sin embargo, cuando hay un final\n
,-n -0
se imprime como podría esperarse de la-
, es decir. imprime todo el archivo ... Por lo tanto, funciona para todos los valores negativos distintos de cero ... pero-0
falla cuando no hay seguimiento\n
head -n -2
no es compatible con POSIX .