0

I want to delete specific two consecutive lines matching patterns from specific line from a file.

For e.g. file contents are like below.

a
b
c
Name: 123
 xyz
Name: 456
 abc

I want to find the lines starting from line 4, matching 1st line pattern starting with Name: and matching 2nd line pattern starting with whitespace and delete the two consecutive lines.

Any efficient way to do this in shell using sed or something else?

To be a bit more clear, I want to remove signing/checksum information from the MANIFEST.MF.

Sample MANIFEST.MF like below. From the below manifest file, I want to remove the entry Name: where Name: entry can be in one line or 2(or more) lines.

Initially my solution was like find the first Name: entry followed by SHA-256-Digest: entry and delete to the end of the file. Unfortunately this solution has a problem of removing one needed entry in the middle. For e.g. NetBeans-Simply-Convertible: is also being removed.

So, now I want to remove Name: entry if available in 1 line or entry spanned across 2 or more lines. But I should not lose entries like NetBeans-Simply-Convertible: while removing Name: entries.

Already I am removing SHA-256-Digest: entries with the below command on file with sed -i "/^\SHA-256-Digest: /d" $manifest_file


Manifest-Version: 1.0
Version-Info: ....

Name: com/abc/xyz/pqr/client/relationship/message/notifier/Relati
 onshipUpdateNotifierFactory.class
SHA-256-Digest: cSSyk6Y2L2F9N6FPtswUkxjF2kelMkGe4bFprcQ+3uY=

Name: com/abc/xyz/pqr/client/relationship/ui/BaseRelationshipView
 $5.class
SHA-256-Digest: w9HgRjDuP024U4CyxeKPYFe6rzuzxZF3b+9LVG36XP8=

Name: com/abc/xyz/pqr/client/impl/MofRelationshipAgentImpl.class
SHA-256-Digest: GwIBIU+UdPtjyRhayAVM90Eo+SwCT/kP65dI59adEnM=

Name: com/abc/xyz/pqr/client/settings/ConvertibleProperties.class
NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}Con
 vertibleProperties
SHA-256-Digest: 5FszAtfpPXcLx/6FBWbfeg6E4fwFMRozV+Q+3rReATc= ...

Expected Output:

Manifest-Version: 1.0
Version-Info: ....


NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}Con
 vertibleProperties

...
3
  • 1
    So you want to delete a line that matches a pattern and the next line after it? Commented Apr 15, 2017 at 6:23
  • 1
    what is the expected output... will line 6 and 7 be deleted as well? and add sample input where it doesn't match and should not be deleted Commented Apr 15, 2017 at 6:26
  • Hi Stephen,Sundeep, I elaborated a bit more about the problem. Please check. Thanks. Commented Apr 16, 2017 at 4:12

5 Answers 5

1

You see that what you are asking is not clear: one answer deletes 4 lines (the two matching and the two subsequent ones); another deletes everything but the matching lines...

I'll throw in what I understand you want: I delete 2 lines, the one matching Name: 123 and the subsequent one. I do this with sed:

sed -e '/Name: 123/{N;d}' filename
1
  • Hi Dario, I elaborated the problem bit more. Please check once. Thanks Commented Apr 16, 2017 at 4:13
0

awk approach:

Let's say we have the following input file file.txt(considering that each line contains Line<number>: as first field):

Line1: a
Line2: b
Line3: c
Line4: Name: 123
Line5:  xyz
Line6: Name: 456
Line7:  abc
Line8: Name: 111
Line9: www
Line10: Num: 222
Line11:  abc
Line12: Name: 333
Line13:  ccc

awk '{ if ($2 == "Name:") { 
           if ((getline l) > 0){ 
               if (l ~ /^\S+  \S+/) { next } else { print $0 RS l }               
           }
       } else { print } 
}' file.txt

The output:

Line1: a
Line2: b
Line3: c
Line8: Name: 111
Line9: www
Line10: Num: 222
Line11:  abc

‘getline var’ - reads the next record from awk's input into the variable var

The getline command returns 1 if it finds a record and 0 if it encounters the end of the file.

1
  • Hi Roman, I elaborated the problem bit more. Please check once. Thanks. Commented Apr 16, 2017 at 4:14
0

Using ed:

$ printf '%s\n' 'g/^ / s///\' '-,.j' 'g/^Name: /d' 'g/SHA-256-Digest: /d' '4,$g/^$/d' ,p Q | ed -s file
Manifest-Version: 1.0
Version-Info: ....

NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}ConvertibleProperties

This applies the following edit script to you input file:

g/^ / s///\
-,.j
g/^Name: /d
g/SHA-256-Digest: /d
4,$g/^$/d
,p
Q

This consists of six separate commands:

  1. The two commands s/// and -,. j applied to every line that starts with a space character. The empty regular expression in the s command re-uses the expression ^ from the preceding g command (which is used for applying one or more commands to lines matching a regular expression), so the s command removes the first empty space on lines that start with empty spaces. The j command then joins the modified line with the previous line. This effectively undoes the wrapping of the lines in the input data.

  2. The command d is applied to all lines that start with Name: , removing these.

  3. Similarly, lines starting with SHA-256-Digest: are removed.

  4. Empty lines are removed from line 4 onwards.

  5. We output the complete buffer to standard output to display the result.

  6. Q quits the editor unconditionally (you could use wq to write the changes back to the original file).

0

Rather than post-processing the file multiple times, you can use something like awk to handle it all in one go. This variant removes the Name and SHA-256-Digest blocks - plus of course their continuation lines, if any.

awk '
    /^$|^[^ ]/ {skip=0}                   # Stop skipping once we hit a blank line or non-space
    /^(Name|SHA-256-Digest):/ {skip=1}    # Start skipping matching headers
    !skip                                 # Output the line unless we are skipping it
' MANIFEST.MF

Output from your example

Manifest-Version: 1.0
Version-Info: ....




NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}Con
 vertibleProperties

It wouldn't be wildly hard to reduce the multiple blank lines to singletons, but as your example output didn't do that I haven't do so either.

You can squash this into one line if you must, but it's not nearly as readable:

awk '/^$|^[^ ]/{skip=0} /^(Name|SHA-256-Digest):/{skip=1} !skip' MANIFEST.MF
-1
sed -e '
   4,$!d;      # skip non-relevant portion
   /Name:/N;   # grab the line coming after Name:
   /\n.* /d;   # what we were after is not this
   P;D
' yourfile
3
  • Hi Rakesh, I elaborated the problem bit more. Please check once. Thanks. Commented Apr 16, 2017 at 4:14
  • HI Rakesh, 4, $!d is deleting the lines from 1 line to 4th line. What I want is, I want to keep the 1st three lines untouched, means I don't want to delete. I wan sed command to act from 4th line. Thanks Commented Apr 16, 2017 at 4:51
  • This appears to produce garbage I afraid. Commented Sep 19, 2023 at 14:15

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.