tags:

views:

770

answers:

3

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.

+1  A: 

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
Jefromi
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
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
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?
Jefromi
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
A: 

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
+1  A: 

You can eliminate one of 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
Thanks, it is a nice way :)
Asaf