How to Delete the Matching Pattern from Given Occurrence

How to delete the matching pattern from given occurrence

Neat sed solution:

sed '/abc/{2,$d}' test.txt
abc
def
ghi
jkl
xyz

sed remove first pattern match only

It's a bit incredible-machiney, but this works:

sed '/PATTERNSTART/,/PATTERNEND/ { // { x; s/$/./; x; }; x; /.../! { x; d; }; x; }' filename

as follows:

/PATTERNSTART/,/PATTERNEND/ {   # in the pattern range
// { # in the first and last line:
x
s/$/./ # increment a counter in the hold buffer by
# appending a character to it. The counter is
# the number of characters in the hold buffer.
x
}
x # for all lines in the range: inspect the
# counter
/.../! { # if it is not three or more (the counter
# becomes three with the start line of the
# second matching range)
x
d # delete the line
}
x
}

The xs in that code are largely to ensure that the counter ends up back in the hold buffer when the whole thing is over. The // bit works because // repeats the last attempted regex, which is the start pattern of the range for its first line and the end pattern for the others.

How can I delete the last occurrence of a pattern in a file using a grep/awk/bash/etc?

If you happen to have GNU coreutils (or you're willing to install them) you can use the occasionally useful tac command to flip the file for processing, allowing you to treat this problem as "remove the first occurrence of the pattern", which is somewhat simpler:

tac /path/to/file | awk '!found && /Hello, world/{found=1;next}1' | tac

Otherwise, you would need to do something like buffer all the lines of the file in memory so that you can print them all out at the end. Or you could process the file twice, the first time just looking for the line number to omit, but that requires that the data be in a file, rather than a stream you're piping into the command:

awk \
-v line="$(grep -hn "hello world" /path/to/file | tail -n1 | cut -f1 -d:)" \
"{NR != line}" /path/to/file

How do I remove multiple occurrences of a pattern from a string in Python?

You basically want to find anything between '<mark' and '/>' so you start with the pattern

r'<mark .* />'

However the .* will be greedy, so to make it non-greedy you need to add a ?, then simply use re.sub to replace those matches with empty string

>>> re.sub(r'<mark .*? />', '', s)
'Bla bla bla bla bla bla. Yadda yadda yadda yadda.'

Using sed to delete all lines between two matching patterns

Use this sed command to achieve that:

sed '/^#/,/^\$/{/^#/!{/^\$/!d}}' file.txt

Mac users (to prevent extra characters at the end of d command error) need to add semicolons before the closing brackets

sed '/^#/,/^\$/{/^#/!{/^\$/!d;};}' file.txt

OUTPUT

# ID 1
$ description 1
blah blah
# ID 2
$ description 2
blah blah
blah blah

Explanation:

  • /^#/,/^\$/ will match all the text between lines starting with # to lines starting with $. ^ is used for start of line character. $ is a special character so needs to be escaped.
  • /^#/! means do following if start of line is not #
  • /^$/! means do following if start of line is not $
  • d means delete

So overall it is first matching all the lines from ^# to ^\$ then from those matched lines finding lines that don't match ^# and don't match ^\$ and deleting them using d.

sed remove a line matching a pattern if not after another matching pattern

awk '/^bar/{if (k) k=0; else next} /^foo/{k=1} 1' file

k means keep the line, it expires at first bar found after foo.

BASH - How to delete a line which contains 2nd occurrence of a pattern string using sed

Following will delete the second line which contains alt_names. Counter c will increase with each line having the pattern matched.

awk '/alt_names/{c++;if(c==2)gsub(/^.*$/,"")}1'
.
[ server ]
subjectAltName = @alt_names
.
.

To modify and save:

awk '/alt_names/{c++;if(c==2)gsub(/^.*$/,"")}1' inputfile >inputfile.tmp && mv inputfile.tmp inputfile

How to delete all lines before the first and after the last occurrence of a string?

Could you please try following. Written and tested with shown samples with GNU awk.

awk '
/Lecture/{
found=1
}
found && NF{
val=(val?val ORS:"")$0
}
END{
if(val){
match(val,/.*Lecture [0-9]+/)
print substr(val,RSTART,RLENGTH)
}
}' Input_file

Explanation: Adding detailed explanation for above.

awk '                                        ##Starting awk program from here.
/Lecture/{ ##Checking if a line has Lecture keyword then do following.
found=1 ##Setting found to 1 here.
}
found && NF{ ##Checking if found is SET and line is NOT NULL then do following.
val=(val?val ORS:"")$0 ##Creating va and keep adding its value in it.
}
END{ ##Starting END block of this code here.
if(val){ ##Checking condition if val is set then do following.
match(val,/.*Lecture [0-9]+/) ##Matching regex till Lecture digits in its value.
print substr(val,RSTART,RLENGTH) ##Printing sub string of matched values here to print only matched values.
}
}' Input_file ##Mentioning Input_file name here.


Related Topics



Leave a reply



Submit