7

I want to delete all the words before a pattern for example: I want to delete all the words before STAC.

Input:

asd
asdd
asddd
STAC
asd
as

Output:

STAC
asd
as

I have this code sed -ni "s/^.*STAC//d" myfile

3
  • If a line has that word it doesn't matter, you just have to eliminate everything that is before that precise word, that is, STAC no HAYSTACK or any combination. Just STAC
    – nicg
    Commented Aug 9, 2019 at 14:48
  • thanks for the comment. I just modified the input
    – nicg
    Commented Aug 9, 2019 at 14:52
  • awk '/^STAC$/,0', awk '$0=="STAC",0', grep -A100000 '^STAC$'
    – user313992
    Commented Aug 10, 2019 at 0:20

5 Answers 5

14

sed works linewise, that's why your try will not work.

So how to do it with sed? Define an address range, starting from the STAC line (/^STAC$/) to the end of the file ($). Those should be printed, so everything else (!) should get deleted:

sed -i '/^STAC$/,$!d' myfile
3
  • 2
    Also possible: sed -ni '/^STAC$/,$p' myfile
    – filbranden
    Commented Aug 9, 2019 at 16:17
  • 1
    This is for GNU sed only. Commented Aug 9, 2019 at 17:03
  • @Christopher Indeed, the -i option requires an argument (extension) for BSD sed and is not part of the standard. While the OP obviously uses GNU sed, your remark is valuable for future readers, so thank you!
    – Philippos
    Commented Aug 9, 2019 at 17:16
8

An awk variant which prints all lines after the match (including the match):

$ awk '/^STAC$/ { out=1 } out' file
STAC
asd
as

This matches the line that only contains the string STAC and sets out to a non-zero value. For each line, if out is non-zero, print it.

Use $0 == "STAC" instead of /^STAC$/ to do a string comparison instead of a regular expression match.


Slightly more obfuscated but shorter, using the boolean result of the match with the regular expression as an integer (will be 0 for a non-match, and 1 for a match):

awk 'p += /^STAC$/' file

If the result in p is non-zero, which it will be from the point where the regular expression first matches, the current line will be printed.

Use p += ($0 == "STAC") instead of p += /^STAC$/ to do a string comparison instead of a regular expression match.

0
7

Another option would be to use a scriptable editor like ed:

printf '%s\n' '1,/^STAC/-1 d' 'wq' | ed -s myfile

This prints two commands to ed:

  • delete lines from 1 through (the line before the one that starts with STAC)
  • write the file back to disk and quit

The -s option inhibits ed's default printing of the number of bytes read & written.

3

Using awk:

awk '/^STAC$/,/$ /' input

This will print all lines between STAC and anything (including the matching lines)


Or using a grep that supports the -z option (BSD grep does not):

Treat input and output data as sequences of lines, each terminated by a zero byte (the ASCII NUL character) instead of a newline.

grep -z 'STAC' input
0
0

grep -wn STAC file.txt | cut -d":" -f 1 | xargs -I % sed '1,%d' file.txt

Get line number of the word, pass it to xargs and use sed to delete.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .