Using sed to write xml tag in Rakefile

142 views Asked by At

I have trying to pre-process a xml-like file by using Rakefile, what I am trying to do is adding a group of xml tags.

The following sed is the short version of what I have done

sed -ig '/TARGET_STRING/{N;G;s/$/<key>KEY_NAME<\/key>/g;}' whateverfile.xml

and this piece of code is worked beautifully and successes while using terminal.

And I put them into the Rakefile I made, like this:

desc 'setup pods archs'
task :setup_podsarchs => :setup_submodules do
    puts 'Altering xml...'.cyan
    `sed -ig '/TARGET_STRING/{N;G;s/$/<key>KEY_NAME<\/key>/g;}' whateverfile.xml`
end

After executing rake, it prompt an error and terminate the task

sed: 1: "/TARGET_STRING/{N;G;s/$/ ...": bad flag in substitute command: 'k'

I had searching around for a long time, cannot find any information about escaping the < and > characters in Ruby.


My platform

  • OS: Mac OS X 10.9
  • Ruby: 2.0.0p247
  • rake: 0.9.6
  • sed: 7

Update

Hi, thank you guys for the extremely fast reply.

and @the Tin Man, for the comment,

What I am trying to do is pre-process the Xcode project file (.pbxproj), which is structured as a xml,

For simplicity, I just show the example of xml structure here:

<dict>
    <key>Key_ONE</key>
    <string>1</string>
</dict>

What I am trying to do is finding the KEY_ONE and adding another key after that:

<dict>
    <key>Key_ONE</key>
    <string>1</string>
    <key>Key_TWO</key>
    <string>2</string>
</dict>
2

There are 2 answers

2
the Tin Man On BEST ANSWER

Using regular expressions for anything beyond the most trivial and controlled parsing leads to madness. Use Nokogiri, an excellent Ruby XML/HTML parser. For instance:

require 'nokogiri'

xml = <<EOT
<xml>
  <foo>foo</foo>
  <bar>bar</bar>
</xml>
EOT

doc = Nokogiri::XML(xml)

doc.at('foo').content = 'bar'
doc.at('bar')['class'] = 'cyan'

puts doc.to_xml

Which outputs:

<?xml version="1.0"?>
<xml>
  <foo>bar</foo>
  <bar class="cyan">bar</bar>
</xml>

Notice the content inside the <foo> tag changed, along with <bar> gaining an attribute.

What's important about using a parser is that the content can change, tag parameters can change, their order can move around inside the tag, tags can be split across multiple lines, and a parser will not care, whereas a regular expression will spout flames and stop working.

2
NeronLeVelu On

parser is better solution.

for sed point of view try with

`sed -ig '/TARGET_STRING/{
    N
    s/$/\
<key>KEY_NAME<\/key>/
    }' whateverfile.xml`

G is normaly not needed because nothing is loaded into g is also not needed, there is onle 1 replacement possible