Search code examples
bashreadlines

Process a line based on lines before and after in bash


I am trying to figure out how to write a bash script which uses the lines immediately before and after a line as a condition. I will give an example in a python-like pseudocode which makes sense to me.

Basically:

for line in FILE:
    if line_minus_1 == line_plus_one:
        line = line_minus_1

What would be the best way to do this?

So if I have an input file that reads:

3
1
1
1
2
2
1
2
1
1
1
2
2
1
2

my output would be:

3
1
1
1
2
2
2
2
1
1
1
2
2
2
2

Notice that it starts from the first line until the last line and respects changes made in earlier lines so if I have:

2
1
2
1
2
2

I would get:

2
2
2
2
2
2

and not:

2
1
1
1
2
2

Solution

  • $ awk 'minus2==$0{minus1=$0} NR>1{print minus1} {minus2=minus1; minus1=$0} END{print minus1}' file
    3
    1
    1
    1
    2
    2
    2
    2
    1
    1
    1
    2
    2
    2
    2
    

    How it works

    • minus2==$0{minus1=$0}

      If the line from 2 lines ago is the same as the current line, then set the line from 1 line ago equal to the current line.

    • NR>1{print minus1}

      If we are past the first line, then print the line from 1 line ago.

    • minus2=minus1; minus1=$0

      Update the variables.

    • END{print minus1}

      After we have finished reading the file, print the last line.

    Multiple line version

    For those who like their code spread over multiple lines:

    awk '
        minus2==$0{
            minus1=$0
        }
    
        NR>1{
            print minus1
        }
    
        {
            minus2=minus1
            minus1=$0
        }
    
        END{
            print minus1
        }
        ' file