1

I have a manifest.xml file in Git, and I need to make a Perl script where I find the fetched path in the file.

For example, fetch="ssh://gerrit-xyz.com". I have to replace just this line with fetch="git://gerrit-xyz.com/projects/aosp".

I don't want to copy the XML file to a new one, because the XML file is huge, and it's not worth it. I just want to find the line through a regular expression (it's normally on 4-5th line in the XML) and replace it with the latter version of fetch.

All the related answers I saw were suggesting to copy in a new file, which is not acceptable in my scenario. How can I do it?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Scharzool
  • 17
  • 6
  • 1
    take a look at [`Tie::File`](http://perldoc.perl.org/Tie/File.html) – chrsblck Aug 13 '13 at 23:46
  • 5
    There is no solution if copying to a new file is not acceptable. Well, you could copy all the material after the material to be replaced to a new location in the file, and then write the new material, but you might find the info for [SO 10467711](http://stackoverflow.com/questions/10467711) useful. This still involves copying all the material after the edit around, which is practically the same as copying the whole file. Only if the old and new material are the same length can you avoid the problem. – Jonathan Leffler Aug 13 '13 at 23:48
  • sed -i 's|fetch="ssh://gerrit-xyz.com"|fetch="git://gerrit-xyz.com/projects/aosp"|g' manifest.xml – phs Aug 13 '13 at 23:52
  • @phs It will copy content of whole file. – Hynek -Pichi- Vychodil Aug 13 '13 at 23:55
  • The handy man page for sed mentions that `-i` means to edit the file in-place. No copy is made. – phs Aug 14 '13 at 00:05
  • Depending on your platform, you may (osx) or may not (linux) need to supply an explicit empty string argument to the option. – phs Aug 14 '13 at 00:06
  • 4
    @phs: If you are on Linux, you could use `strace -o sed.strace sed -i.bak -e 's/=/@@/' somefile` to see what `sed -i` does. You can leave out the backup extension if you want. In both cases, you will see `sed` create a new file, write to it, then rename the files. (Note that this means that if the file has multiple hard links, `sed -i` breaks the links. If a file is a symlink, the symlink is broken and replaced by a local file.) In other words, the 'in place edit' mode makes a new file with the output. On other platforms, use `truss` or `dtrace` or other similar tools for the same analysis. – Jonathan Leffler Aug 14 '13 at 00:27
  • @chrsblck : Tie::File works really good. It's just that now my perl script has a dependency to have "Tie::File" if I plan to deploy my script somewhere else. That's fine enough. Thanks a lot – Scharzool Aug 15 '13 at 00:28
  • @ShardulBhakta That shouldn't be an issue, as `Tie::File` is a core module. – chrsblck Aug 15 '13 at 04:19

1 Answers1

6

If replacement has not exactly same length, there is no way to change it without copying of at least rest of file.

Hynek -Pichi- Vychodil
  • 26,174
  • 5
  • 52
  • 73
  • 2
    If the line has not exactly same length you can't. It is how data is stored in file on disc. It is just bunch of bytes. Imagine it like you have pointer which you can move around. You can replace some bytes by others but bytes after pointer doesn't move. – Hynek -Pichi- Vychodil Aug 13 '13 at 23:54