CarlosBernardes
CarlosBernardes

Reputation: 1

How to replace first occurrence after skipping a first match using sed

Imagine I have the following piece of text:

<Data>
    <Country>
       <Name>Portugal<\Name>
       <Population>10M</Population>
       <Sub>
          <Code>Y</Code>
       </Sub>
    </Country>
    <Country>
       <Name>Spain<\Name>
       <Population>30M</Population>
       <Sub>
          <Code>Y</Code>
       </Sub>
    </Country>
</Data>

How can I replace the Y to N from Country Portugal without replacing the Code from the remaining countries?

I've tried to use sed:

sed -i '/<Country>Portugal<\/Country>/{s/Y/N/;}' file.xml

but this is not replacing anything.

Can you tell me what I am doing wrong? How can I replace the first occurrence of Y AFTER matching the Portugal ?

Thanks!

Upvotes: 0

Views: 267

Answers (4)

Ed Morton
Ed Morton

Reputation: 204628

If your input is really always exactly that format then all you need is:

$ awk '/<Name>/{f=/Portugal/} f && /<Code>/{sub(/Y/,"N")} 1' file
<Data>
    <Country>
       <Name>Portugal<\Name>
       <Population>10M</Population>
       <Sub>
          <Code>N</Code>
       </Sub>
    </Country>
    <Country>
       <Name>Spain<\Name>
       <Population>30M</Population>
       <Sub>
          <Code>Y</Code>
       </Sub>
    </Country>
</Data>

Upvotes: 0

Paul Hodges
Paul Hodges

Reputation: 15438

Use a range match.

sed '/<Name>Portugal</,/<\/Country>/ s/<Code>Y</<Code>N</' file.xml

(Edited to match updated requirements.)

Upvotes: 0

potong
potong

Reputation: 58578

This might work for you (GNU sed):

sed '/<Country>/{:a;N;/<\/Country>/!ba;/Portugal/s/Y/N/}' /file

Gather up the lines for a Country then match those lines to contain Portugal and replace the first Y with N.

Upvotes: 0

that other guy
that other guy

Reputation: 123690

Avoid parsing XML with regex. Use an XML processing tool like xmlstarlet:

$ cat foo.xml
<Data>
  <Country>
    <Name>Portugal</Name>
    <Population>10M</Population>
    <Sub>
      <Code>Y</Code>
    </Sub>
  </Country>
  <Country>
    <Name>Spain</Name>
    <Population>30M</Population>
    <Sub>
      <Code>Y</Code>
    </Sub>
  </Country>
</Data>

$ xmlstarlet edit --update '/Data/Country[Name="Portugal"]/Sub/Code' -v "N" foo.xml
<?xml version="1.0"?>
<Data>
  <Country>
    <Name>Portugal</Name>
    <Population>10M</Population>
    <Sub>
      <Code>N</Code> 
    </Sub>
  </Country>
  <Country>
    <Name>Spain</Name>
    <Population>30M</Population>
    <Sub>
      <Code>Y</Code>
    </Sub>
  </Country>
</Data>

Upvotes: 2

Related Questions