4

Basically I have 2 files. One has a list of router and switch login prompts, like this:

user@router1
user@router2
user@switch1
user@switch2

The other file has blocks of XML, like this:

<headTag>
    <anotherTag1>
    <anotherTag2>
    </anotherTag2>
    </anotherTag1>
</headTag>
<headTag>
    <anotherTag1>
    <anotherTag2>
    </anotherTag2>
    </anotherTag1>
</headTag>

So what I want to do is this, I need to loop though the XML file and each time it detects <headTag> place the next item on the router/switch list on the line above it, so the final output would end up like this:

user@router1
<headTag>
    <anotherTag1>
    <anotherTag2>
    </anotherTag2>
    </anotherTag1>
</headTag>
user@router2
<headTag>
    <anotherTag1>
    <anotherTag2>
    </anotherTag2>
    </anotherTag1>
</headTag>

How can I achieve this? I am using Red Hat Enterprise Linux Server and have approximately 800 items in the router/switch list and the same number of XML blocks.

4

Here another short solution with sed and ed.

It modify the XML file inplace. Ignore the output to the console.

sed -e 's#.*#/<headTag>/i\n&\n.\n//\nw#' PATH_TO_LIST_FILE | ed PATH_TO_XML_FILE

The sed commands line writes following Ed commands for each line in the list file:

/<headTag>/i                # search for tag and insert before
user@router1                # text to insert (= the current line in the list file)
.                           # end of insert
//                          # skip current tag (we are now on the line above the current tag))
w                           # save (could be postponed to the end, but makes the command shorter...)

For this command it is needed that <headTag> is always at the beginning of a line in the xml file.

  • 2
    Please comment before down-voting. – jofel May 23 '13 at 13:08
  • I just tried this and the result was this repeatedly for each result: 153528 ? ? ? – SJB May 23 '13 at 13:30
  • @Campino The command modify the xml directly. Ignore its output to the terminal. I added this hint now to the answer. – jofel May 23 '13 at 13:41
  • 1
    +1 Neat trick! I know this is rich coming from the guy who proposed a perl answer, but it feels a bit "write-only" :) – Joseph R. May 23 '13 at 13:56
  • Oh... I see it now! That works great! I can't even upvote this because I don't have enough repuatation, but it is fantastic! – SJB May 23 '13 at 14:04
0

Here you go:

perl -MTie::File -e '
$xml_file_name="path_to_xml_file";
$list_file_name="path_to_list_file";
tie @xml_lines,"Tie::File",$xml_file_name;
tie @list_lines,"Tie::File",$list_file_name;
@offsets = grep {$xml_lines[$_]=~/\Q<headTag>\E/} (0..$#xml_lines);
@offsets=reverse @offsets;
splice @xml_lines,pop @offsets,0,pop @list_lines;'

Diclaimer

  • This code will modify your XML file in place. Make a backup copy if you don't want the original clobbered.
  • This code is untested. Backup both files before trying it.

Edit

Fixed a typo: note the added tilde ~ on line 6.

  • 2
    Thanks, I will try this on my personal Linux box at home before attempting in a production environment. – SJB May 23 '13 at 11:34
  • Always a good idea... – Joseph R. May 23 '13 at 11:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.