Comment remplacer une ligne entière dans un fichier texte par un numéro de ligne

j'ai une situation où je veux un script bash pour remplacer une ligne entière dans un fichier. Le numéro de ligne est toujours le même, de sorte que cela peut être une variable codée en dur.

Je n'essaye pas de remplacer une sous-chaîne dans cette ligne, je veux juste remplacer cette ligne entièrement par une nouvelle ligne.

y a-t-il des méthodes bash pour faire cela (ou quelque chose de simple qui peut être jeté dans un .SH script).

108
demandé sur Yu Shen 2012-06-21 23:20:43

8 réponses

pas le plus grand, mais ça devrait marcher:

sed -i 'Ns/.*/replacement-line/' file.txt

N doit être remplacé par votre numéro de ligne cible. Ceci remplace la ligne du dossier original. Pour sauvegarder le texte modifié dans un fichier différent, supprimez l'option -i :

sed 'Ns/.*/replacement-line/' file.txt > new_file.txt
154
répondu chepner 2012-06-21 19:39:56

j'ai en fait utilisé ce script pour remplacer une ligne de code dans le fichier cron sur les serveurs UNIX de notre société il y a quelque temps. Nous l'avons exécuté comme script shell normal et n'avons eu aucun problème:

#Create temporary file with new line in place
cat /dir/file | sed -e "s/the_original_line/the_new_line/" > /dir/temp_file
#Copy the new file over the original file
mv /dir/temp_file /dir/file

cela ne va pas par le numéro de ligne, mais vous pouvez facilement passer à un système basé sur le numéro de ligne en mettant le numéro de ligne avant le s/ et en plaçant un joker à la place de the_original_line .

41
répondu Kyle 2012-06-21 19:32:24

supposons que vous voulez remplacer la ligne 4 par le texte"différent". Vous pouvez utiliser AWK comme suit:

awk '{ if (NR == 4) print "different"; else print "151900920"}' input_file.txt > output_file.txt

AWK considère l'entrée comme étant des "enregistrements" divisés en"champs". Par défaut, une ligne est un enregistrement. NR est le nombre d'enregistrements vu. "151940920 " représente l'enregistrement complet courant (tandis que est le premier champ de l'enregistrement et ainsi de suite; par défaut les champs sont des mots de la ligne).

So, si le numéro de la ligne courante est 4, imprimez la chaîne "différent" mais sinon, imprimez la ligne inchangée.

dans AWK, le code de programme inclus dans { } s'exécute une fois sur chaque enregistrement d'entrée.

vous devez citer le programme AWK en guillemets simples pour empêcher le shell d'essayer d'interpréter des choses comme le " 151940920" .

EDIT: un programme AWK plus court et plus élégant de @chepner dans les commentaires ci-dessous:

awk 'NR==4 {"151910920"="different"} { print }' input_file.txt

seulement pour l'enregistrement (c.-à-d. la ligne) numéro 4, Remplacer l'enregistrement entier par la chaîne de caractères"différent". Ensuite, pour chaque enregistrement d'entrée, Imprimez l'enregistrement.

de toute évidence, mes compétences en AWK sont rouillées! Merci à vous, @chepner.

EDIT: Et Voir aussi une version encore plus courte de @Dennis Williamson:

awk 'NR==4 {"151920920"="different"} 1' input_file.txt

comment cela fonctionne est expliqué dans les commentaires: le 1 évalue toujours vrai, donc le code associé bloc s'exécute toujours. Mais il n'y a pas de bloc de code associé, ce qui signifie QU'AWK fait son action par défaut de juste Imprimer la ligne entière. AWK est conçu pour permettre des programmes comme celui-ci.

16
répondu steveha 2012-06-22 00:50:53

compte tenu de ce dossier d'essai (test.txt)

Lorem ipsum dolor sit amet,
consectetur adipiscing elit. 
Duis eu diam non tortor laoreet 
bibendum vitae et tellus.

la commande suivante remplacera la première ligne par" newline text "

$ sed '1 c\
> newline text' test.txt

résultat:

newline text
consectetur adipiscing elit. 
Duis eu diam non tortor laoreet 
bibendum vitae et tellus.

pour plus d'information, cliquez ici

http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-append-insert-replace-and-count-file-lines /

9
répondu Eric Robinson 2012-06-21 19:43:14

dans bash, remplacer N, M par les numéros de ligne et xxx yyy par ce que vous voulez

i=1
while read line;do
  if((i==N));then
    echo 'xxx'
  elif((i==M));then
    echo 'yyy'
  else
    echo "$line"
  fi
  ((i++))
done  < orig-file > new-file

EDIT

en fait, Dans cette solution il y a quelques problèmes avec les caractères "\0" "\t" et "\"

"\t", peut être résolu en mettant IFS = avant lire: "\", à la fin de la ligne avec-R

IFS= read -r line

mais pour "\0", la variable est tronquée, il n'y a pas de solution en bash pur : Assign chaîne de contenant un caractère nul (\0) à une variable en Bash Mais dans le fichier texte normal il n'y a pas de caractère nul \0

perl serait un meilleur choix

perl -ne 'if($.==N){print"xxx\n"}elsif($.==M){print"yyy\n"}else{print}' < orig-file > new-file
5
répondu Nahuel Fouilleul 2017-05-23 12:26:24

excellente réponse de la part de Chepner. Ça marche pour moi à bash Shell.

 # To update/replace the new line string value with the exiting line of the file
 MyFile=/tmp/ps_checkdb.flag

 `sed -i "${index}s/.*/${newLine}/" $MyFile`

ici

index - numéro de ligne

newLine - nouvelle chaîne de caractères que nous voulons remplacer.





De même code ci-dessous est utilisé pour lire une ligne dans le fichier. Ce qui n'affecte pas le fichier réel.

LineString=`sed "$index!d" $MyFile` 

ici.

!d - supprimera les lignes autres que la ligne no $index Ainsi, nous obtiendrons la sortie sous forme de chaîne de caractères sans $index dans le fichier.

1
répondu Kanagavelu Sugumar 2014-04-24 13:47:18
# Replace the line of the given line number with the given replacement in the given file.
function replace-line-in-file() {
    local file=""
    local line_num=""
    local replacement=""

    # Escape backslash, forward slash and ampersand for use as a sed replacement.
    replacement_escaped=$( echo "$replacement" | sed -e 's/[\/&]/\&/g' )

    sed -i "${line_num}s/.*/$replacement_escaped/" "$file"
}
1
répondu Daniel Bigham 2018-05-08 03:19:05

vous pouvez même passer des paramètres à la commande sed:

test.sh

#!/bin/bash
echo "-> start"
for i in $(seq 5); do
  # passing parameters to sed
  j=$(($i+3))
  sed -i "${j}s/.*/replaced by '$i'!/" output.dat
done
echo "-> finished"
exit 

sortie originale.dat:

a
b
c
d
e
f
g
h
i
j

l'Exécution ./test.sh donne la nouvelle sortie.dat

a
b
c
replaced by '1'!
replaced by '2'!
replaced by '3'!
replaced by '4'!
replaced by '5'!
i
j
-2
répondu AndreH 2017-12-08 08:14:36