3
find . -type f -name "test.php" -print0 | xargs -0 egrep -sHnl "&\s*new\s"| xargs gsed -i.bak 's/&\(\s*new\s\)/\1/gi' -

This works fine to replace the selected file.
But I want to look at the difference between the original and replaced files at the same time.

find . -type f -name "test.php" -print0 | xargs -0 egrep -sHnl "&\s*new\s"| xargs gsed -i.bak 's/&\(\s*new\s\)/\1/gip' -

This attempt fails, but also duplicate the lines which are replaced.

find . -type f -name "test.php" -print0 | xargs -0 egrep -sHnl "&\s*new\s"| xargs gsed -n 's/&\(\s*new\s\)/\1/p' -

This works but do neither overwrite the original file( i.e. not makes it change with replaced text) nor backup.

With this inspiration, I tried following, but doesn't work.

find . -type f -name "test.php" -print0 | xargs -0 egrep -sHnl "&\s*new\s"| xargs gsed -i.bak 's/&\(\s*new\s\)/\1/gip;s/.*\n//' -

How can I achieve it?

marcolz
  • 2,880
  • 2
  • 23
  • 28
Damegami
  • 37
  • 5
  • 1
    Your question appears to be about a single file, so why confuse things with `find | xargs`? Reduce the question to its basic elements. – William Pursell Mar 13 '18 at 14:04
  • 1
    If you want to review the differences between the original and the new file, the simplest thing to do is to write the new data to a new file and call `diff`. Trying to do "in-place editing" is just making your problem more difficult. – William Pursell Mar 13 '18 at 14:07
  • William Pursell@ You are right. But I have to replace every file in my domain so practically, I use this command because it's not needed to write each parent path if you use 'find'. – Damegami Mar 14 '18 at 00:14
  • William Pursell@ Yes, right. And also using editor with diff plugin is the simplest thing, they are added additional process to work though. – Damegami Mar 14 '18 at 00:18
  • Write a simple script that solves your problem for one file. Use `find` and `xargs` to invoke that script. Reducing your question to its basic elements is directly mirrored in your solution; reduce the problem to its basic components and solve each one individually. This is one of the conceptual problems of using `sed -i`; it prevents the user from learning to decompose the problem. – William Pursell Mar 14 '18 at 15:40

3 Answers3

0

Alright boss,

maybe the w option of sed can help. here is a start;

[root@volte1 test]# cat scr.sh
sed -i '/ligne/{
s//line/g
w /dev/stdout
}' file.txt



[root@volte1 test]# cat file.txt
line1
line2
line3
line4
ligne5
line6
line7


[root@volte1 test]# ./scr.sh
line5


[root@volte1 test]# cat file.txt
line1
line2
line3
line4
line5
line6
line7

Also try the following to output file before/after difference:

$ cat scr2.sh
find . -name file.txt -printf '\n%p:\n' -exec sed -i '/ligne/{
h
s//line/g
H
x
s/\n/ >>> /
w /dev/fd/2
x
}' {} \;
The HCD
  • 492
  • 8
  • 18
0

You don't show any sample input/output so idk what it is you're really trying to do but to make changes inplace in a file while printing the before/after lines to stderr would be trivial with GNU awk instead of the GNU sed you're using:

find . -type f -name "test.php" -print0 |
xargs -0 awk -i inplace '{
    print "Before:", $0 | "cat>&2"
    sub(/old_regexp/,"new_string")
    print "After:", $0 | "cat>&2"
} 1'

You don't need grep when you're using awk (any time you're using pipes of grep+sed or multiple seds or multiple greps you should probably be using a single awk command instead) so whatever that grep command is doing can be just included in the awk script and you could just use -exec ... + instead of -print0 | xargs -0 for efficiency.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

Make sed replace text in a file in-place and also display the substituted lines on screen

You could do:

sed 's/pattern/Rstring/g' InputFile | tee OutputFile | sed -n '/Rstring/p'

Here pattern is the text to be replaced and Rstring is the replacement string.

builder-7000
  • 7,131
  • 3
  • 19
  • 43