Operating System - HP-UX
1748008 Members
4980 Online
108757 Solutions
New Discussion

Re: How can I delete entire lines based on a search expression in vi?

 
SOLVED
Go to solution
H.Merijn Brand (procura
Honored Contributor

Re: How can I delete entire lines based on a search expression in vi?

vi

 

  :g,</Customer>,s,^,<SelfBillingIndicator>0</SelfBillingIndicator>\n,

 

(if your version of vi does not support \n, use Ctrl-V - Enter)

 

perl

 

 $ perl -pe'm{ </Customer>} and print "<SelfBillingIndicator>0</SelfBillingIndicator>\n"' file.xml

Enjoy, Have FUN! H.Merijn
Eric Antunes
Honored Contributor

Re: How can I delete entire lines based on a search expression in vi?

Hi again,

 

The vi command worked perfectly with Ctrl-V-Enter.

 

Now, I have this pattern:

 

    <BillingAddress>
      <AddressDetail>Stuffs a</AddressDetail>
      <City>Stuffs b</City>
      <PostalCode>Stuffs c</PostalCode>
      <Country>Stuffs d</Country>
    </BillingAddress>
    <ShipFromAddress>
      <AddressDetail/>
      <City/>
      <PostalCode/>
      <Country/>
    </ShipFromAddress>

 

And would like to correct/fiil the ShipFromAddress part with the BillingAddress data, to look like this:

 

 

    <BillingAddress>
      <AddressDetail>Stuffs a</AddressDetail>
      <City>Stuffs b</City>
      <PostalCode>Stuffs c</PostalCode>
      <Country>Stuffs d</Country>
    </BillingAddress>
    <ShipFromAddress>
      <AddressDetail>Stuffs a</AddressDetail>
      <City>Stuffs b</City>
      <PostalCode>Stuffs c</PostalCode>
      <Country>Stuffs d</Country>

    </ShipFromAddress>

This is really getting harder...

 

Thank you,

 

Eric

Each and every day is a good day to learn.
Eric Antunes
Honored Contributor

Re: How can I delete entire lines based on a search expression in vi?

I'm trying things like this in vi:

 

:g,<AddressDetail/>,6^Uyy6^D,s,p

 

:g,<AddressDetail/>,!6^Uyy6^D,s,p

 

:g,<AddressDetail/>,6^U,yy,6^D,s,p

For this last one, vi says "U: Not an editor command"

 

But no success for now...

Each and every day is a good day to learn.
H.Merijn Brand (procura
Honored Contributor

Re: How can I delete entire lines based on a search expression in vi?

By the time your requirements get as complicated as this, you should not want to "solve" that in vi

 

I'd suggest perl, but I am clearly biased

 

Take the suggestions from this thread and create yourself a simple perl script that modifies the original file and outputs the result to *another* file, so you can then alter the script as long and often as you want till you get where you want to be.

 

Of course we can help with the specifics, but in order to believe in this new approach you will have to follow your own signature: learn something new every day. Don't be affraid this new approach will take too long. Its time lost is regained manyfold very very soon after. When I see the time span between your posts, the time you would have needed to learn the basics would already have been regained. 

Enjoy, Have FUN! H.Merijn
James R. Ferguson
Acclaimed Contributor

Re: How can I delete entire lines based on a search expression in vi?

HI Eric:

 

A Perl script that meets your requirements might be:

 

#!/usr/bin/perl
use strict;
use warnings;
my $insert = 0;
my @a = ();
while (<>) {
    if (m{<BillingAddress>}..m{</BillingAddress>}) {
        $insert = 1;
        if (m{</?BillingAddress>}) {
            print;
            next;
        }
        push @a, $_;
    }
    if (m{<ShipFromAddress>}..m{</ShipFromAddress>}) {
        print if m{</?ShipFromAddress>};
        if ($insert) {
            $insert = 0;
            print @a;
            @a = ();
        }
        next;
    }
    print;
}
1;

Assuming you called the script 'reformat', run it as:

 

# ./reformat file

 

Regards!

 

...JRF...

H.Merijn Brand (procura
Honored Contributor

Re: How can I delete entire lines based on a search expression in vi?

JRF, s/\A/#/ :)

 

(first line of a script starts with #!/path/to/program (the # was missing)

 

More serious, once you get here, it might be worth looking at XML parser modules and modify the content in a more structural way. When done, use the module's methods to write valid XML to disk 

Enjoy, Have FUN! H.Merijn
Eric Antunes
Honored Contributor

Re: How can I delete entire lines based on a search expression in vi?

Ok, Merijn, I'm not so unscriptable ;)

 

The script ran wonderfuly with just a little change in the file and script from <BillingAddress> to <FBillingAddress> because there were other <BillingAddress> I didn't want to be found:

 

./MyFirstPerlScrit.pl file-to-format.xml > file-formated.xml

 

Thanks,

 

Eric

 

 

Each and every day is a good day to learn.
James R. Ferguson
Acclaimed Contributor

Re: How can I delete entire lines based on a search expression in vi?


@H.Merijn Brand (procura wrote:

JRF, s/\A/#/ :)

 

(first line of a script starts with #!/path/to/program (the # was missing)

 

More serious, once you get here, it might be worth looking at XML parser modules and modify the content in a more structural way. When done, use the module's methods to write valid XML to disk 


Yes, thanks for pointing out the absent interpreter line :-)  I editted my post to reflect that change.

 

I know you are correct when you note that the XML parser modules are far better than the roll-your-own method I chose.  The decent into HTML or XML hell can be steep and slippery :-)  Thanks, Merijn!

 

Regards!

 

...JRF...

James R. Ferguson
Acclaimed Contributor

Re: How can I delete entire lines based on a search expression in vi?


@Eric Antunes wrote:

The script ran wonderfuly with just a little change in the file and script from <BillingAddress> to <FBillingAddress> because there were other <BillingAddress> I didn't want to be found:

 


Hi (again) Eric:

 

If it was only the first stanza that you wanted to change, a slight code change would have enabled you to leave your input file alone.

 

Change these lines:

 

if (m{<BillingAddress>}..m{</BillingAddress>}) {
       
if (m{<ShipFromAddress>}..m{</ShipFromAddress>}) {

 TO:

 

if (m?<BillingAddress>?..m?</BillingAddress>?) {
        
if (m?<ShipFromAddress>?..m?</ShipFromAddress>?) {

That is, alter the match delimiter from "{" and "}" to "?" and "?".

 

This will match one pattern range, only.

 

Regards!

 

...JRF...

H.Merijn Brand (procura
Honored Contributor

Re: How can I delete entire lines based on a search expression in vi?

Or use the triple-dot

from 'man perlop'

   Range Operators
       Binary ".." is the range operator, which is really two different
       operators depending on the context.  In list context, it returns a list
       of values counting (up by ones) from the left value to the right value.
       If the left value is greater than the right value then it returns the
       empty list.  The range operator is useful for writing "foreach (1..10)"
       loops and for doing slice operations on arrays. In the current
       implementation, no temporary array is created when the range operator
       is used as the expression in "foreach" loops, but older versions of
       Perl might burn a lot of memory when you write something like this:

           for (1 .. 1_000_000) {
               # code
           }

       The range operator also works on strings, using the magical auto-
       increment, see below.

       In scalar context, ".." returns a boolean value.  The operator is
       bistable, like a flip-flop, and emulates the line-range (comma)
       operator of sed, awk, and various editors.  Each ".." operator
       maintains its own boolean state.  It is false as long as its left
       operand is false.  Once the left operand is true, the range operator
       stays true until the right operand is true, AFTER which the range
       operator becomes false again.  It doesn't become false till the next
       time the range operator is evaluated.  It can test the right operand
       and become false on the same evaluation it became true (as in awk), but
       it still returns true once.  If you don't want it to test the right
       operand till the next evaluation, as in sed, just use three dots
       ("...") instead of two.  In all other regards, "..." behaves just like
       ".." does.

 Personally I have never ever felt the need for ??

YMMV TIMTOWTDI 

 

Enjoy, Have FUN! H.Merijn