4

I use sed to substitute text in files. I want to give sed a file which contains all the strings to be searched and replaced in a given file.

It goes over .h and .cpp files. In each file it searches for file names which are included in it. If found, it substitutes for example "a.h" with "<a.h>" (without the quotes).

The script is this:

For /F %%y in (all.txt) do 
   for /F %%x in (allFilesWithH.txt) do
       sed -i s/\"%%x\"/"\<"%%x"\>"/ %%y
  • all.txt - List of files to do the substitution in them
  • allFilesWithH.txt - All the include names to be searched

I don't want to run sed several times (as the number of files names in input.txt.) but I want to run a single sed command and pass it input.txt as input.

How can I do it?

P.S I run sed from VxWorks Development shell, so it doesn't have all the commands that the Linux version does.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Asaf
  • 83
  • 1
  • 2
  • 9

3 Answers3

7

You can eliminate one of the loops so sed only needs to be called once per file. Use the -f option to specify more than one substitution:

For /F %%y in (all.txt) do 
    sed -i -f allFilesWithHAsSedScript.sed %%y

allFilesWithHAsSedScript.sed derives from allFilesWithH.txt and would contain:

s/\"file1\"/"\<"file1"\>"/
s/\"file2\"/"\<"file2"\>"/
s/\"file3\"/"\<"file3"\>"/
s/\"file4\"/"\<"file4"\>"/

(In the article Common threads: Sed by example, Part 3 there are many examples of sed scripts with explanations.)

Don't get confuSed (pun intended).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
4

sed itself has no capability to read filenames from a file. I'm not familiar with the VxWorks shell, and I imagine this is something to do with the lack of answers... So here are some things that would work in bash - maybe VxWorks will support one of these things.

sed -i 's/.../...' `cat all.txt`

sed -i 's/.../...' $(cat all.txt)

cat all.txt | xargs sed -i 's/.../...'

And really, it's no big deal to invoke sed several times if it gets the job done:

cat all.txt | while read file; do sed -i 's/.../.../' $file; done

for file in $(cat all.txt); do   # or `cat all.txt`
    sed -i 's/.../.../' $file
done
Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • Thanks, I will try it. It is a big problem because it takes too much time and too much memory to be done. This is why i searched for another way. I hope it would help. Thank you. – Asaf Oct 05 '09 at 15:41
  • Running sed over and over won't use any more memory than running it once. It will take a little more time to run as there is overhead in spawning new processes, and I suppose also in the regexp being constructed each time. If you are desperate to avoid that overhead then using Perl instead of sed might be quicker. – Tim Oct 05 '09 at 16:04
  • Agreed. Multiple sequential invocations cannot increase memory usage, especially not with a program like sed which works line-by-line. Time, of course, will be affected. Of course, if you have enough small files (if they're big, the replace is most of the time) for it to be a problem, you could be getting into the too-long-command-line regime. In any case, this is why I provided the first few methods. I guess the shell doesn't have command substitution, then? – Cascabel Oct 05 '09 at 19:59
  • Actually, now with the suggested way it runs much faster. The problem was that the PF Usage went over 2GB and then i wasnt able to run more sed commands. – Asaf Oct 06 '09 at 09:44
0

What I'd do is change allFilesWithH.txt into a sed command using sed.

(When forced to use sed. I'd actually use Perl instead, it can also do the search for *.h files.)

reinierpost
  • 8,425
  • 1
  • 38
  • 70