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, il peut donc s'agir d'une variable codée en dur.
Je n'essaie pas de remplacer une sous-chaîne dans cette ligne, je veux juste remplacer cette ligne entièrement par une nouvelle ligne.
Y at-il des méthodes bash pour faire cela (ou quelque chose de simple qui peut être jeté dans un script .sh).
Pas le meilleur, mais ça devrait marcher:
sed -i 'Ns/.*/replacement-line/' file.txt
où N
devrait être remplacé par votre numéro de ligne cible. Ceci remplace la ligne dans le fichier d'origine. Pour enregistrer le texte modifié dans un autre fichier, supprimez l'option -i
:
sed 'Ns/.*/replacement-line/' file.txt > new_file.txt
En fait, j'ai 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é en tant que script shell normal et nous 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 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 caractère générique à la place de the_original_line
.
Supposons que vous souhaitiez remplacer la ligne 4 par le texte "différent". Vous pouvez utiliser AWK comme ceci:
awk '{ if (NR == 4) print "different"; else print $0}' input_file.txt > output_file.txt
AWK considère que l'entrée est "des enregistrements" divisés en "champs". Par défaut, une ligne correspond à un enregistrement. NR
est le nombre d'enregistrements vus. $0
représente l'enregistrement complet en cours (tandis que $1
est le premier champ de l'enregistrement et ainsi de suite; par défaut, les champs sont des mots de la ligne).
Donc, si le numéro de ligne actuel est 4, affichez la chaîne "différente" mais sinon, affichez la ligne sans modification.
Dans AWK, le code de programme inclus dans { }
ne s'exécute qu'une fois sur chaque enregistrement d'entrée.
Vous devez citer le programme AWK entre guillemets pour empêcher le shell d’essayer d’interpréter des éléments tels que le $0
.
EDIT: Un programme AWK plus court et plus élégant de @chepner dans les commentaires ci-dessous:
awk 'NR==4 {$0="different"} { print }' input_file.txt
Remplacez l’enregistrement complet par la chaîne "différente" uniquement pour l’enregistrement (ligne) du numéro 4. Ensuite, pour chaque enregistrement d'entrée, imprimez-le.
Clairement mes compétences AWK sont rouillées! Merci, chepner.
EDIT: et voyez aussi une version encore plus courte de @Dennis Williamson:
awk 'NR==4 {$0="different"} 1' input_file.txt
Comment cela fonctionne est expliqué dans les commentaires: le 1
évalue toujours la valeur true et le bloc de code associé est toujours exécuté. Mais il n'y a pas de bloc de code associé, ce qui signifie qu'AWK effectue son action par défaut en imprimant simplement la ligne entière. AWK est conçu pour permettre des programmes laconiques comme celui-ci.
Étant donné ce fichier de test (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.
plus d'informations peuvent être trouvées ici
http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-append-insert-replace-and-count-file-lines/
en bash, remplacez 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
MODIFIER
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 de lire: "\", en fin de ligne avec -r
IFS= read -r line
mais pour "\ 0", la variable est tronquée, il n'y a pas de solution dans pure bash: Affecter une chaîne contenant un caractère nul (\ 0) à une variable dans Bash Mais dans un fichier texte normal, aucun 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
# Replace the line of the given line number with the given replacement in the given file.
function replace-line-in-file() {
local file="$1"
local line_num="$2"
local replacement="$3"
# 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"
}
Excellente réponse de Chepner. Cela fonctionne 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`
iciindex
- Numéro de lignenewLine
- nouvelle chaîne que nous souhaitons remplacer.
De même, le code ci-dessous est utilisé pour lire une ligne particulière du fichier. Cela n'affectera pas le fichier réel.
LineString=`sed "$index!d" $MyFile`
ici!d
- supprimera les lignes autres que la ligne no $index
Nous obtiendrons donc le résultat sous forme de chaîne de caractères non associée à $index
dans le fichier.
Sur mac j'ai utilisé
sed -i '' -e 's/text-on-line-to-be-changed.*/text-to-replace-the=whole-line/' file-name