GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo mover una línea en un archivo de texto hacia arriba o hacia abajo una línea?

Tengo algunos archivos de texto y me gustaría poder mover una línea arbitraria en cualquiera de los archivos hacia arriba o hacia abajo (las líneas al principio o al final del archivo permanecerían donde están). Tengo algo de código que funciona, pero parece confuso y no estoy convencido de tener todos los casos extremos cubiertos, así que me pregunto si hay alguna herramienta o paradigma que lo haga mejor (por ejemplo, más fácil de entender el código (para otros lectores o en 6 meses), más fácil de depurar y más fácil de mantener; "más eficiente" no es muy importante).

move_up() {
  # fetch line with head -<line number> | tail -1
  # insert that one line higher
  # delete the old line
  sed -i -e "$((line_number-1))i$(head -$line_number $file | tail -1)" -e "${line_number}d" "$file"
}

move_down() {
  file_length=$(wc -l < "$file")
  if [[ "$line_number" -ge $((file_length - 1)) ]]; then
    # sed can't insert past the end of the file, so append the line
    # then delete the old line
    echo $(head -$line_number "$file" | tail -1) >> "$file"
    sed -i "${line_number}d" "$file"
  else
    # get the line, and insert it after the next line, and delete the original
    sed -i -e "$((line_number+2))i$(head -$line_number $file | tail -1)" -e "${line_number}d" "$file"
  fi
}

Puedo verificar errores de entradas dentro o fuera de estas funciones, pero puntos de bonificación si las entradas incorrectas (como números no enteros, archivos inexistentes o números de línea mayores que la longitud del archivo) se manejan con cordura.

Quiero que se ejecute en un script Bash en sistemas Debian/Ubuntu modernos. No siempre tengo acceso raíz, pero puedo esperar que se instalen herramientas "estándar" (piense en un servidor web compartido) y puede poder solicitar la instalación de otras herramientas si puedo justificar la solicitud (aunque siempre es mejor tener menos dependencias externas).

Ejemplo:

$ cat b
1
2
3
4
$ file=b line_number=3 move_up
$ cat b
1
3
2
4
$ file=b line_number=3 move_down
$ cat b
1
3
4
2
$ 

Respuesta aceptada:

Similar a Archemar Sugerencia, podría escribir esto con ed :

printf %s\n ${linenr}m${addr} w q | ed -s infile

es decir,

linenr                      #  is the line number
m                           #  command that moves the line
addr=$(( linenr + 1 ))      #  if you move the line down
addr=$(( linenr - 2 ))      #  if you move the line up
w                           #  write changes to file
q                           #  quit editor

p.ej. para mover la línea no. 21 una fila arriba:

printf %s\n 21m19 w q | ed -s infile

para mover la línea no. 21 una línea hacia abajo:

printf %s\n 21m22 w q | ed -s infile

Pero dado que solo necesita mover una determinada línea hacia arriba o hacia abajo una línea, también podría decir que prácticamente desea intercambiar dos líneas consecutivas. Conoce a sed :

sed -i -n 'addr{h;n;G};p' infile

es decir,

addr=${linenr}           # if you move the line down
addr=$(( linenr - 1 ))   # if you move the line up
h                        # replace content of the hold  buffer with a copy of the pattern space
n                        # read a new line replacing the current line in the pattern space  
G                        # append the content of the hold buffer to the pattern space
p                        # print the entire pattern space

p.ej. para mover la línea no. 21 una fila arriba:

sed -i -n '20{h;n;G};p' infile

para mover la línea no. 21 una línea hacia abajo:

sed -i -n '21{h;n;G};p' infile

Usé gnu sed sintaxis anterior. Si la portabilidad es una preocupación:

sed -n 'addr{
h
n
G
}
p' infile

Aparte de eso, las comprobaciones habituales:el archivo existe y se puede escribir; file_length > 2; line_no. > 1; line_no. < file_length;


Linux
  1. Cómo agregar texto al final del archivo en Linux

  2. ¿Cómo encontrar corchetes no coincidentes en un archivo de texto?

  3. ¿Cómo analizar cada línea de un archivo de texto como un argumento para un comando?

  4. VIM:cómo ir a la línea exacta en Ubuntu

  5. ¿Cómo agrego texto a un archivo?

Cómo mover un archivo en Linux

Cómo leer archivos línea por línea en Bash

Cómo leer un archivo línea por línea en Bash

¿Cómo se reemplaza el texto similar a sed con python?

¿Cómo canalizo una llamada de subproceso a un archivo de texto?

¿Cómo cargar un archivo por FTP desde la línea de comandos?