How do we use sed to replace specific line with a string variable?
Solution 1
Assuming the value of $substitute doesn't contain special characters, you can simply do:
line=1
substitute=hello1
sed -i "${line}s/.*/$substitute/" file.txt
Solution 2
With perl:
export line substitute
perl -pi -e '$_ = $ENV{substitute} . "\n" if $. == $ENV{line}' file.txt
same with GNU awk:
export line substitute
gawk -i inplace 'NR == ENVIRON["line"] {$0 = ENVIRON["substitute"]}
{print}' file.txt
Using sed is not ideal here, even with those that support a perl-like -i option, as we'd need to do some post-processing on the value of $substitute if it may contain backslash, &, the s command delimiter or newline characters. See How to ensure that string interpolated into `sed` substitution escapes all metachars for details on that.
Solution 3
Without further information, the following awk program should work:
awk -v where="$line" -v what="$substitute" 'FNR==where {print what; next} 1' file.txt
- It will import the shell variables
$lineand$substituteintoawkvariableswhereandwhat. - When processing the file, it will by default simply print the current line ( the seemingly stray
1outside the rule block{ ... }). - When the per-file line counter
FNRis equal to the line number stored inwhere, we print the substitute stringwhatinstead, and skip execution to the next input line.
Note that awk doesn't edit files in-place, so you have to redirect the output and rename the result file once you are satisfied. Alternatively, with sufficiently new versions of GNU awk, you can use the -i inplace option to modify the file in-place.
Note that (as pointed out by αғsнιη/Stéphane Chazelas/Ed Morton) the above will show erratic behavior if your substitute string contains the literal \, since this method expands escape sequences. In that case, the awk-based alternative solution in Stéphane Chazelas' answer with exporting the variable and referencing it as ENVIRON["substitute"] would do the trick (see this answer for more information).
Solution 4
Assuming line >0 and always is int, you could do:
<infile head -n$(($line-1)); printf '%s\n' "$substitute"; tail -n +$(($line+1)) infile
Note that this will append the $substitute value to the end of file if line_number $line > file's_number_of_lines
Solution 5
$ line=1 substitute=hello1
$ sed -nf - <<eof file
$line r $(t=$(mktemp);printf '%s\n' "$substitute" > "$t";echo "$t")
$line!p
eof
We use a heredoc to pass the sed code. The sed code is reading a file and placing jts contents on the stdout and suppressing the original line by virtue of the -n option.
Related videos on Youtube
Jerry
Updated on September 18, 2022Comments
-
Jerry 9 monthsLets say for example I have a
file.txtcontaining 3 lines:hello hello helloI have a variable called
line=1and a variable stringsubstitute=hello1. I want to replace the string in the line described by the variablelinewith my new string variable calledsubstitute.The resultant change to
files.txtwould look like:hello1 hello helloHow would I use
sedto do this? Orawk? If thats what you are in to, as long as I can input variables that I can change in a while loop. -
Ed Morton over 2 yearsConsiderline="$line" substitute="$substitute" gawk '...'on a single line so you don't have to export the variables. -
Jeff Schaller over 2 yearsPlease take note of the link in Stéphane's answer regarding the need to escape arbitrary data in (e.g.) the $substitute variable.