Daniel Standage
Daniel Standage

Reputation: 8314

In-place processing with grep

I've got a script that calls grep to process a text file. Currently I am doing something like this.

$ grep 'SomeRegEx' myfile.txt > myfile.txt.temp
$ mv myfile.txt.temp myfile.txt

I'm wondering if there is any way to do in-place processing, as in store the results to the same original file without having to create a temporary file and then replace the original with the temp file when processing is done.

Of course I welcome comments as to why this should or should not be done, but I'm mainly interested in whether it can be done. In this example I'm using grep, but I'm interested about Unix tools in general. Thanks!

Upvotes: 39

Views: 30117

Answers (9)

2anoyu
2anoyu

Reputation: 9

cat myfile.txt | grep 'sometext' > myfile.txt

This will find sometext in myfile.txt and save it back to myfile.txt, this will accomplish what you want. Not sure about regex, but it does work for text.

Upvotes: -3

Julio C.A.T.
Julio C.A.T.

Reputation: 7

Store in a variable and then assign it to the original file:

A=$(cat aux.log | grep 'Something') && echo "${A}" > aux.log

Upvotes: -1

Alexey
Alexey

Reputation: 526

sponge (in moreutils package in Debian/Ubuntu) reads input till EOF and writes it into file, so you can grep file and write it back to itself.

Like this:

grep 'pattern' file | sponge file

Upvotes: 38

kenorb
kenorb

Reputation: 166833

To edit file in-place using vim-way, try:

$ ex -s +'%!grep foo' -cxa myfile.txt

Alternatively use sed or gawk.

Upvotes: 1

High Performance Mark
High Performance Mark

Reputation: 78364

Most installations of sed can do in-place editing, check the man page, you probably want the -i flag.

Upvotes: 2

Andy Lester
Andy Lester

Reputation: 93795

Take a look at my slides "Field Guide To the Perl Command-Line Options" at http://petdance.com/perl/command-line-options.pdf for more ideas on what you can do in place with Perl.

Upvotes: -2

ghostdog74
ghostdog74

Reputation: 342949

Perl has the -i switch, so does sed and Ruby

sed -i.bak -n '/SomeRegex/p' file

ruby -i.bak -ne 'print if /SomeRegex/' file

But note that all it ever does is creating "temp" files at the back end which you think you don't see, that's all.

Other ways, besides grep

awk

awk '/someRegex/' file > t && mv t file

bash

while read -r line;do case "$line" in *someregex*) echo "$line";;esac;done <file > t && mv t file

Upvotes: 20

j_random_hacker
j_random_hacker

Reputation: 51316

In general, this can't be done. But Perl has the -i switch:

perl -i -ne 'print if /SomeRegEx/' myfile.txt

Writing -i.bak will cause the original to be saved in myfile.txt.bak.

(Of course internally, Perl just does basically what you're already doing -- there's no special magic involved.)

Upvotes: 5

The Archetypal Paul
The Archetypal Paul

Reputation: 41769

No, in general it can't be done in Unix like this. You can only create/truncate (with >) or append to a file (with >>). Once truncated, the old contents would be lost.

Upvotes: 4

Related Questions