GNU/Linux >> Tutoriels Linux >  >> Linux

Comment déplacer une ligne vers le haut ou vers le bas d'une ligne dans un fichier texte ?

J'ai des fichiers texte et j'aimerais pouvoir déplacer une ligne arbitraire dans l'un des fichiers vers le haut ou vers le bas d'une ligne (les lignes au début ou à la fin du fichier resteraient là où elles sont). J'ai du code qui fonctionne mais il semble kludgy et je ne suis pas convaincu d'avoir couvert tous les cas limites, donc je me demande s'il existe un outil ou un paradigme qui le fait mieux (par exemple, plus facile à comprendre le code (pour d'autres lecteurs ou moi en 6 mois), plus facile à déboguer et plus facile à maintenir ; "plus efficace" n'est pas très important).

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
}

Je peux effectuer une vérification des erreurs des entrées à l'intérieur ou à l'extérieur de ces fonctions, mais les points bonus si une mauvaise entrée (comme des nombres non entiers, des fichiers inexistants ou des numéros de ligne supérieurs à la longueur du fichier) sont gérés sainement.

Je veux qu'il s'exécute dans un script Bash sur les systèmes Debian/Ubuntu modernes. Je n'ai pas toujours un accès root, mais je peux m'attendre à ce que des outils "standard" soient installés (pensez à un serveur Web partagé), et peut pouvoir demander l'installation d'autres outils si je peux justifier la demande (bien que moins de dépendances externes soit toujours mieux).

Exemple :

$ 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
$ 

Réponse acceptée :

Similaire à Archemar la suggestion de, vous pouvez écrire ceci avec ed :

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

c'est-à-dire

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

par exemple. pour déplacer la ligne no. 21 une ligne :

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

pour déplacer la ligne no. 21 une ligne vers le bas :

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

Mais comme vous n'avez qu'à déplacer une certaine ligne vers le haut ou vers le bas d'une ligne, vous pouvez également dire que vous voulez pratiquement échanger deux lignes consécutives. Rencontrez sed :

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

c'est-à-dire

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

par exemple. pour déplacer la ligne no. 21 une ligne :

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

pour déplacer la ligne no. 21 une ligne vers le bas :

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

J'ai utilisé gnu sed syntaxe ci-dessus. Si la portabilité est un problème :

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

A part cela, les vérifications habituelles :le fichier existe et est accessible en écriture; file_length > 2; line_no. > 1; line_no. < file_length;


Linux
  1. Comment ajouter des numéros de ligne aux fichiers texte sous Linux

  2. Comment ajouter une ligne d'en-tête et de fin à un fichier sous Linux

  3. Comment lister un nom de fichier par ligne de sortie sous Linux ?

  4. Comment remplacer sed comme texte par python?

  5. Comment diriger un appel de sous-processus vers un fichier texte ?

Comment déplacer un fichier sous Linux

Comment lire des fichiers ligne par ligne dans Bash

Comment lire un fichier ligne par ligne dans Bash

VIM :comment aller à la ligne exacte sur Ubuntu

Comment ajouter du texte à un fichier ?

Comment diviser un fichier texte en plusieurs fichiers *.txt ?