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
$line
and$substitute
intoawk
variableswhere
andwhat
. - When processing the file, it will by default simply print the current line ( the seemingly stray
1
outside the rule block{ ... }
). - When the per-file line counter
FNR
is equal to the line number stored inwhere
, we print the substitute stringwhat
instead, 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 over 1 year
Lets say for example I have a
file.txt
containing 3 lines:hello hello hello
I have a variable called
line=1
and a variable stringsubstitute=hello1
. I want to replace the string in the line described by the variableline
with my new string variable calledsubstitute
.The resultant change to
files.txt
would look like:hello1 hello hello
How would I use
sed
to 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 3 yearsConsider
line="$line" substitute="$substitute" gawk '...'
on a single line so you don't have to export the variables. -
Jeff Schaller over 3 yearsPlease take note of the link in Stéphane's answer regarding the need to escape arbitrary data in (e.g.) the $substitute variable.