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).
8 réponses
pas le plus grand, mais ça devrait marcher:
sed -i 'Ns/.*/replacement-line/' file.txt
où 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
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
.
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.
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 /
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
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.
# 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"
}
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