14

Im trying to make a substitution of a single line in a file with awk, for example

changing this:

e1 is (on)

e2 is (off)

to:

e1 is (on)

e2 is (on)

use command:

awk '/e2/{gsub(/off/, "on")};{print}' ~/Documents/Prueba > ~/Documents/Prueba

this makes the substitution but the file ends blank!

gdoron
  • 147,333
  • 58
  • 291
  • 367
Josepas
  • 349
  • 1
  • 2
  • 12

5 Answers5

30

Another answer, using a different tool (sed, and the -i (in place) flag)

sed -i '/e2/ s/off/on/' ~/Documents/Prueba
David Souther
  • 8,125
  • 2
  • 36
  • 53
25

Your awk is correct, however you are redirecting to the same file as your original. This is causing the original file to be overwritten before it has been read. You'll need to redirect the output to a different file.

awk '/e2/{gsub(/off/, "on")};{print}' ~/Documents/Prueba > ~/Documents/Prueba.new

Rename Prueba.new afterwards if necessary.

qbert220
  • 11,220
  • 4
  • 31
  • 31
6

As explained by the other answers and in the question "Why reading and writing the same file through I/O redirection results in an empty file in Unix?", the shell redirections destroy your input file before it is read.

To solve that problem without explicitly resorting to temporary files, have a look at the sponge command from the moreutils collection.

awk '/e2/{gsub(/off/, "on")};{print}' ~/Documents/Prueba | sponge ~/Documents/Prueba

Alternatively, if GNU awk is installed on your system, you can use the in place extension.

gawk -i inplace '/e2/{gsub(/off/, "on")};{print}' ~/Documents/Prueba
Charles Plessy
  • 330
  • 3
  • 7
4

You can also use cat to read the file first, then use pipe to redirect to stdout, then read with awk from stdin:

cat ~/Documents/Prueba | awk '/e2/{gsub(/off/, "on")};{print}' - > ~/Documents/Prueba

I believe the dash - is optional, since you're only reading stdin.

Some interesting documentation: https://www.gnu.org/software/gawk/manual/html_node/Naming-Standard-Input.html

GabrielF
  • 2,071
  • 1
  • 17
  • 29
1

You cannot redirect the output to the same file as the input file. Choose another file name.

The > will empty your file at the first place.


You can try sponge.

kev
  • 155,172
  • 47
  • 273
  • 272