-2

How to keep previous and current line if the previous line contains common text?

I have a main file like this:

Hello_world
Anna
Frank
Jeremy
Hello_earth
Jessie
James

I would want 3 output files like this:

Output file 1 (Only has the string with the previous hello)

Hello_world,Anna
Hello_earth,Jessie

Output file 2 (Only has the string WITHOUT previous hello)

Frank
Jeremy
James

Output file 3 (Only has the string with the previous hello and including Hi to string without hello from previous line )

Hello_world,Anna
Hello_earth,Jessie
Hi,Frank
Hi,Jeremy
Hi,James

I have tried using grep and awk but was not able to get the desired output

1
  • 2
    So the common text is always 'Hello_'? Can there be no names between two hellos? Lastly, would be nice if you posted what you already tried with awk.
    – seshoumara
    Feb 8, 2023 at 5:23

4 Answers 4

1

More of a job for awk:

awk -v OFS=, '
  /^Hello_/{
    getline name
    print $0, name > "file1"
    print $0, name > "file3"
    next
  }
  {
    print > "file2"
    s = s "Hi" OFS $0 ORS
  }
  END {
   printf "%s", s > "file3"
  }' < input
0

Below is a GNU sed script. It uses the special 'W' (capital w) command, that appends to file only the first line, not the entire pattern space. This is used for the 'no_name' edge case, see below.

#!/usr/bin/sed -nrf

/^Hello_/{
    :new
        $b no_name
        N
        /\nHello_/b no_name
        b first_name
        :no_name
            s:^[^\n]+:&,:
            W output_1.txt
            W output_3.txt
            s:^[^\n]+\n?::
            /./b new
            $b other_names
        :first_name
            s:\n:,:
            w output_1.txt
            w output_3.txt
}
/^Hello_/!H
${
    :other_names
        x
        s:^\n::
        w output_2.txt
        /./s:^:Hi,:mg
        w output_3.txt
}

To test a few edge cases like the nonexistence of a name after the 'Hello_' keyword, I appended to the example input file: Hello_foo\nHello_bar. Output:

==> output_1.txt <==
Hello_world,Anna
Hello_earth,Jessie
Hello_foo,
Hello_bar,
==> output_2.txt <==
Frank
Jeremy
James
==> output_3.txt <==
Hello_world,Anna
Hello_earth,Jessie
Hello_foo,
Hello_bar,
Hi,Frank
Hi,Jeremy
Hi,James
0

Tested in gnu linux and freebsd:

sed '
  /^Hello/!b1
  N;s/\n/,/w file1
  b
  :1
  w file2
  s/^/Hi,/;H
  $!d;x
  s/^\n//
' file >file3

We write double lines to file1 and output to stdout. We write single lines to file2 and append to pattern space, which we output at the end to stdout and redirect to file3.

0

Not sure about your intended output2 and 3. This is what I think you may have meant:

$ <hello paste -d, - - | sed -n '/Hello/p'
Hello_world,Anna
Hello_earth,Jessie

$ sed '/Hello/ d' hello 
Anna
Frank
Jeremy
Jessie
James

$ (sed -n '/Hello/p' hello ;sed  '/Hello/d' hello)
Hello_world
Hello_earth
Anna
Frank
Jeremy
Jessie
James

where:

$ cat hello 
Hello_world
Anna
Frank
Jeremy
Hello_earth
Jessie
James

You must log in to answer this question.

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