¿Hay alguna forma de ignorar las líneas de encabezado en UNIX?

Tengo un archivo de campo de ancho fijo que trato de ordenar usando la utilidad de ordenamiento UNIX (Cygwin, en mi caso).

El problema es que hay un encabezado de dos líneas en la parte superior del archivo que se ordena en la parte inferior del archivo (ya que cada línea de encabezado comienza con dos puntos).

¿Hay alguna manera de decir ordenar, ya sea “pasar las dos primeras líneas sin clasificar” o especificar un orden que ordene las líneas de dos puntos hasta la parte superior? Las líneas restantes siempre comienzan con un número de 6 dígitos (que en realidad es la clave I estoy clasificando) si eso ayuda.

Ejemplo:

:0:12345 :1:6:2:3:8:4:2 010005TSTDOG_FOOD01 500123TSTMY_RADAR00 222334NOTALINEOUT01 477821USASHUTTLES21 325611LVEANOTHERS00 

debería ordenar a:

 :0:12345 :1:6:2:3:8:4:2 010005TSTDOG_FOOD01 222334NOTALINEOUT01 325611LVEANOTHERS00 477821USASHUTTLES21 500123TSTMY_RADAR00 

 (head -n 2  && tail -n +3  | sort) > newfile 

Los paréntesis crean una subshell, terminando la stdout para que pueda canalizarla o redirigirla como si procediera de un solo comando.

Si no te importa usar awk , puedes aprovechar las habilidades de pipa incorporadas de awk

p.ej.

 extract_data | awk 'NR<3{print $0;next}{print $0| "sort -r"}' 

Esto imprime las dos primeras líneas al pie de la letra y canaliza el rest por sort .

Tenga en cuenta que esto tiene la ventaja muy específica de poder seleccionar selectivamente partes de una entrada canalizada. todos los otros métodos sugeridos solo ordenarán los archivos simples que se pueden leer varias veces. Esto funciona en cualquier cosa.

Aquí hay una versión que funciona en datos canalizados:

 (read -r; printf "%s\n" "$REPLY"; sort) 

Si su encabezado tiene varias líneas:

 (for i in $(seq $HEADER_ROWS); do read -r; printf "%s\n" "$REPLY"; done; sort) 

Esta solución es de aquí

Puede usar tail -n +3 | sort ... tail -n +3 | sort ... (tail generará el contenido del archivo desde la tercera línea).

 head -2  && nawk 'NR>2'  | sort 

ejemplo:

 > cat temp 10 8 1 2 3 4 5 > head -2 temp && nawk 'NR>2' temp | sort -r 10 8 5 4 3 2 1 

Solo toma 2 líneas de código …

 head -1 test.txt > a.tmp; tail -n+2 test.txt | sort -n >> a.tmp; 

Para datos numéricos, se requiere -n. Para el orden alfa, el -n no es obligatorio.

Archivo de ejemplo:
$ cat test.txt

encabezamiento
8
5
100
1
-1

Resultado:
$ cat a.tmp

encabezamiento
-1
1
5
8
100

Con Python:

 import sys HEADER_ROWS=2 for _ in range(HEADER_ROWS): sys.stdout.write(next(sys.stdin)) for row in sorted(sys.stdin): sys.stdout.write(row) 

Aquí hay una función de shell bash derivada de las otras respuestas. Maneja tanto archivos como pipas. El primer argumento es el nombre del archivo o ‘-‘ para stdin. Los argumentos restantes se pasan a sort. Un par de ejemplos:

 $ hsort myfile.txt $ head -n 100 myfile.txt | hsort - $ hsort myfile.txt -k 2,2 | head -n 20 | hsort - -r 

La función de shell:

 hsort () { if [ "$1" == "-h" ]; then echo "Sort a file or standard input, treating the first line as a header."; echo "The first argument is the file or '-' for standard input. Additional"; echo "arguments to sort follow the first argument, including other files."; echo "File syntax : $ hsort file [sort-options] [file...]"; echo "STDIN syntax: $ hsort - [sort-options] [file...]"; return 0; elif [ -f "$1" ]; then local file=$1; shift; (head -n 1 $file && tail -n +2 $file | sort $*); elif [ "$1" == "-" ]; then shift; (read -r; printf "%s\n" "$REPLY"; sort $*); else >&2 echo "Error. File not found: $1"; >&2 echo "Use either 'hsort  [sort-options]' or 'hsort - [sort-options]'"; return 1 ; fi } 

Esto es lo mismo que Ian Sherbin, pero mi implementación es:

 cut -d'|' -f3,4,7 $arg1 | uniq > filetmp.tc head -1 filetmp.tc > file.tc; tail -n+2 filetmp.tc | sort -t"|" -k2,2 >> file.tc; 

Así que aquí hay una función bash donde los argumentos son exactamente como sort. Soporte de archivos y tuberías.

 function skip_header_sort() { if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then local file=${@: -1} set -- "${@:1:$(($#-1))}" fi awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file } 

Cómo funciona. Esta línea verifica si hay al menos un argumento y si el último argumento es un archivo.

  if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then 

Esto guarda el archivo en un argumento separado. Ya que estamos a punto de borrar el último argumento.

  local file=${@: -1} 

Aquí eliminamos el último argumento. Como no queremos pasarlo como un argumento de ordenación.

  set -- "${@:1:$(($#-1))}" 

Finalmente, hacemos la parte awk, pasando los argumentos (menos el último argumento si era el archivo) para ordenar awk. Esto fue sugerido originalmente por Dave y modificado para tomar argumentos de clasificación. Confiamos en que $file estará vacío si estamos canalizando, por lo tanto, ignorado.

  awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file 

Ejemplo de uso con un archivo separado por comas.

 $ cat /tmp/test A,B,C 0,1,2 1,2,0 2,0,1 # SORT NUMERICALLY SECOND COLUMN $ skip_header_sort -t, -nk2 /tmp/test A,B,C 2,0,1 0,1,2 1,2,0 # SORT REVERSE NUMERICALLY THIRD COLUMN $ cat /tmp/test | skip_header_sort -t, -nrk3 A,B,C 0,1,2 2,0,1 1,2,0 
 cat file_name.txt | sed 1d | sort 

Esto hará lo que quieras.