简体   繁体   中英

Delete lines before and after a match within a specified tags in SED

Need to delete before and after of a matching pattern within the tag

< mds:insert> 
    < attributeValues>
        < AttrNames
            < Item Value="MyContact_c"/>
        < /AttrNames>
    < /attributeValues>
< /mds:insert>

Using

sed -i -n '/MyContact_c/{s/.*//;x;d;};x;p;${x;p;}' $file

removes only line before and after the matching pattern, need to delete all the contents within the mds:insert tag... Any pointers will be helpful.

It isn't sed , but here is one for ex using the snippet you posted as the file content for $file :

kitsune:~$ printf '%s\n' 'set ic
1;/="MyContact_c"/<|?<mds:insert?+;/<\/mds:insert>/-d
%p' | ex -s $file

Output:

<mds:insert>
</mds:insert>

That will print the remains of the file after the first instance of the section is removed. If you want this done for all instances, the command line will look like this:

'set ic
g/="MyContact_c"/<|?<mds:insert?+;/<\/mds:insert>/-d
%p'

You can use this in the for loop of a shell script if you want this done to multiple files. Naturally you'll want a backup copy if you do such a thing, so make sure to copy the file before altering it if you intend to overwrite it.

By the way, if you've ever used Vim or even vi, these sorts of commands are used for saving, quitting, etc. It is worth adding ex to your toolbox of knowledge IMHO.

Edit

C Shell users cannot use these commands as-is because they contain quoted newlines, which isn't allowed in a C shell. Instead, you can modify the first command like so:

kitsune:~% printf '%s\n%s\n%s\n' 'set ic' '1;/="MyContact_c"/<|?<mds:insert?+;/<\/mds:insert>/-d' '%p' | ex -s $file

You can similarly do the same with the other string.

Disclaimer: I'm not a C shell user myself, so there might be a better way, but I don't know it.

Here's one way to do it in sed:

sed -e ':a' -e '/ mds:insert/!{p;d;}' -e 'N;/\/mds:insert/{/MyContact_c/!p;d;};ba' filename

You and I may be using different versions of sed or something. Let's try an experiment:

sed -e '/ mds:insert/!{p;d;}' filename

It won't do anything very interesting, but I want to know whether it generates an error.

Here is a way to do it with awk

awk '{a[NR]=$0} /MyContact_b/ {f=NR} END {for (i=1;i<=NR;i++) if (i+2<f || i-2>f || !f) print a[i]}' file
< mds:insert>
< /mds:insert>

It skips two line before and two after pattern if its found.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM