Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I've this sed & find command

find /home/www/ -name footer.php -exec sed -i 's/<\/body>/testmoe\n<\/body>/'

what I need to replace testmoe with data in file.txt so its gona be ,

find /home/www/ -name footer.php -exec sed -i 's/<\/body>/file.txt\n<\/body>/'

any suggestion to correct my command

share|improve this question
    
Your question isn't clear. Do you want to add testmo\n before </body> and then at some later date change testmo to file.txt? –  Iain May 7 '11 at 8:24
    
i want to add text from file.txt before </body> –  user47556 May 7 '11 at 8:39
    
file.txt include like 4 lines –  user47556 May 7 '11 at 8:39

3 Answers 3

To improve a little on @Iain's answer, I think you can do it in just one pass like this:

#!/bin/sh
sed -i '/<\/body/ {
    r /path/to/file
    a </body>
    d
}' $1

This searches for </body>, inserts the file into the buffer, appends </body> to the buffer, and then deletes the original </body>, which as Iain correctly pointed out can't be moved.

share|improve this answer
    
The sed-fu is stronger in this one! –  Iain May 7 '11 at 23:13
1  
Haha! Definitely not, I only came to this after reading your answer. –  Eduardo Ivanec May 7 '11 at 23:15
    
This is a great solution - thanks. –  Iain May 7 '11 at 23:31
    
I've been scouring the toobs for this info, ++ –  Sophistifunk Aug 4 '11 at 4:14

With sed you have to make multiple passes as the /RE/r <filename> command inserts the contents of <filename> into the output after the /RE/. The easiest way to do this with sed is to

  • Insert 'marker text' before the /RE/ in pass one
  • Insert the contents of the file after the 'marker text' in pass two
  • Delete the 'marker text' in pass three

This is most easily achieved with a script which you can call from find

#!/bin/bash

sed -i '/<\/body>/i xyzzy' $1
sed -i '/xyzzy/r /path/to/file.txt' $1
sed -i  '/xyzzy/d' $1

then

find /home/www -name footer.php -exec /path/to/script {} \;
share|improve this answer
1  
Ooooh, cunning! The sed-fu is strong in this one. –  MadHatter May 7 '11 at 21:59
1  
This is quite nice. I think you can do it without the marker text though, I posted that variation as a separate answer. –  Eduardo Ivanec May 7 '11 at 23:05

I know it's a bit like the old West Country joke ("Do you know how to get to Yeovil?" "If I wanted to get to Yeovil, I wouldn't start from here, sir.") but I wouldn't use sed.

Try

perl -ne '$temp = $_ ; if ( $_ =~ /<\/body>/ ) { open FD2, "file.txt" ; while (<FD2>) { print  $_ ; } } ; print $temp;' < foo > bar

perl one-liners can be a bit, well, cryptic, so here's a breakdown of what's happening. The perl script:

  1. perl -n loops through STDIN line-by-line; for each line -e invokes the script in single-quotes, in which:
  2. $temp = $_ stores the line in a temporary buffer
  3. if ( $_ =~ /<\/body>/ ) looks for a line containing </body>
  4. open FD2, "file.txt" ; while (<FD2>) { print $_ ; }: when </body> has been found, opens a file descriptor to file.txt and in a subloop reads through each line in that file and writes it to STDOUT; the re-use of $_ in this loop is why we had to temporarily store it in step 2
  5. print $temp; writes the line originally read to STDOUT regardless of whether a match was found in step 3

The practical upshot is that each line of STDIN is written to STDOUT, but if any line happens to contain </body>, the entire contents of file.txt are inserted before that line is written out.

Is that what you wanted? If so, wrapping it in find, redirecting STDIN and STDOUT, and renaming STDOUT on top of STDIN after execution, is left as an exercise for you. You should also note that if you happen to have more than one occurrence of </body> in your file, you'll get the contents of file.txt intercalated each time it occurs.

share|improve this answer
2  
+1 for creative excuse to use perl oneliner. –  Caleb May 7 '11 at 13:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.