2

how to delete only the line from xml file ( with sed/awk or perl one liner line )

that start with:

<units> 

and ended with

</Networks>

as the follwoing

<units><unit ip= ............   </units><ranges/></Networks>
6
  • 4
    You understand that this leaves you with an xml file that is syntactically incorrect, i.e. you're missing the closing </Networks> tag by removing the line.
    – wurtel
    Mar 16, 2015 at 10:45
  • yes I know that ( the first Networks exist on the top of the file Mar 16, 2015 at 10:46
  • 2
    Why do you need an ill formed XML file?
    – choroba
    Mar 16, 2015 at 10:47
  • dont worry later I will append new lines that will be in place that line Mar 16, 2015 at 10:49
  • 4
    Looks like an XY problem to me. What are you -actually- trying to accomplish? Parsing XML with regex is a bad idea, because there's lots of ways it can go wrong. Creating malformed XML deliberately is also a bad idea, for much the same reason. What problem are you trying to solve? I will probably suggest the answer is - use an XML parser, not a regex. With a bit more XML as a sample, this is actually very easy to do.
    – Sobrique
    Mar 16, 2015 at 11:11

3 Answers 3

4

Do not use regular expressions to parse XML. It's an excellent way to create brittle code, because there's a bunch of perfectly valid things you can do with XML which will break a regex. Things like reformatting the XML in entirely valid ways (such as 'pretty printing' it in a nested/indented form) will break your code.

Instead I would suggest - use an XML parser. Personally, I like the XML::Twig module in perl.

Your comment suggests that what you're trying to do is add stuff to a <Networks> element in your XML.

So how about something like this:

#!/usr/bin/perl
use strict;
use warnings;

use XML::Twig;

my $xml_text = '<XML>
<Networks><units><unit ip="1.2.3.4" /></units><ranges/></Networks>
</XML>';

my $parser = XML::Twig->new( 'pretty_print' => 'indented' );
#would probably use 'parsefile' instead here
$parser->parse($xml_text);

print "\nBefore:\n";
$parser->print;


#insert a new element into 'Networks':
$parser->root->first_child('Networks')->insert_new_elt(
        'last_child',     #position - end of "Networks" element
        'new_element',    #element
        {   'attribute_here'    => "value_here",
            'another_attribute' => 'another_value',
        },                 #attributes as key value pairs
        "Content_here",    #element content
    );


print "\nAfter:\n";
$parser->print;
3

Try this:

perl -i -pe 's|^<units>.*</Networks>$||' /my/filename

Note that if you have leading or trailing space in the line you will need this instead:

perl -i -pe 's|^ *<units>.*</Networks> *$||' /my/filename

I uesd pipe as a separator rather than slash to avoid unnecessary escaping.

2
  • I'll now leave you to be partonised by the regulars: if you're an expert, you already know the issues, and if not you will learn them by trying this. Mar 16, 2015 at 11:40
  • the units line is only the one unit line in the XML so I not see any problem here Mar 16, 2015 at 12:04
0

Since you indicate that you are aware that this will break your XML, you can do what you want with one of these:

  1. Perl

    perl -ne 'print unless m#^<units>.*</Networks>$#' file.xml 
    perl -ne 'm#^<units>.*</Networks>$# ? next : print' file.xml 
    
  2. awk

    awk '!/^<units>.*<\/Networks>$/' file.xml 
    
  3. sed

    sed '/^<units>.*<\/Networks>$/d' file.xml 
    
  4. grep

    grep -Ev '^<units>.*<\/Networks>$' file.xml 
    
  5. Bash (and zsh), for the sake of completion

    while read -r line; do 
        [[ "$line" =~ ^\<units\>.*\<\/Networks\>$ ]] || printf "%s\n" "$line"
    done < file.xml 
    
6
  • The awk one is a really (no pun intended) awkward way of doing it. Why not awk '!/<units>.*<\/Networks>/'
    – user78605
    Mar 16, 2015 at 13:56
  • You need the ! before it or else it will only print that line
    – user78605
    Mar 16, 2015 at 14:43
  • @JID fixed, I wrote too fast
    – terdon
    Mar 16, 2015 at 14:49
  • Sorry, you are also missing the last / :(
    – user78605
    Mar 16, 2015 at 15:09
  • 1
    @JID yes, that's what I get for editing on my phone. Thanks. Next time though, please edit the post directly to fix this sort of thing.
    – terdon
    Mar 16, 2015 at 15:15

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.