How do we use sed to replace specific line with a string variable?

6,234

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 into awk variables where and what.
  • 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 in where, we print the substitute string what 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.

Share:
6,234

Related videos on Youtube

Jerry
Author by

Jerry

Updated on September 18, 2022

Comments

  • Jerry
    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 string substitute=hello1. I want to replace the string in the line described by the variable line with my new string variable called substitute.

    The resultant change to files.txt would look like:

    hello1
    hello
    hello
    

    How would I use sed to do this? Or awk? If thats what you are in to, as long as I can input variables that I can change in a while loop.

  • Ed Morton
    Ed Morton over 3 years
    Consider line="$line" substitute="$substitute" gawk '...' on a single line so you don't have to export the variables.
  • Jeff Schaller
    Jeff Schaller over 3 years
    Please take note of the link in Stéphane's answer regarding the need to escape arbitrary data in (e.g.) the $substitute variable.