Search code examples
linuxgrep

Grep every other line of a file


Is there a way to grep every other line of a line? For example, just grep the odd or even lines only of a file.

I read the man page for grep and I don't see such option. I also want to get the line after the match

grep -A1 (some option here to only look at odd lines) "pattern" filename

The command I am using in my perl script:

@rows = `LANG=en_US.UTF-8 grep --include="image_args_search_*.txt" --exclude-dir=".misc" --exclude-dir=".image_args" --exclude-dir=".image_args_clean" --exclude-dir=".image_args_text" --exclude-dir=".image_args_\
init" --exclude-dir=".misc" --exclude-dir="buscar" --exclude-dir=".config" --exclude-dir="*_bak*" --exclude-dir="indexacao_de_*" --exclude-dir="*.cgi" --exclude-dir="*.pl" --exclude-dir="imagens" --exclude-dir="loaded\
_dispenses" --exclude-dir="1o_tabeliao_de_notas_de_jundiai" --exclude-dir="*_orig" --exclude-dir="checar" --exclude-dir="indexar" --no-group-separator -A1 -iHIER "$operator" $include_dirs`;

Thanks!


Solution

  • You could use a modulo operation to check whether the number is odd or even. You can use:

    $ pattern="..." # replace this with your pattern
    $ awk -v p="$pattern" '{if ($0~p && (NR % 2)) {print}}' file # odd rows matching pattern
    $ awk -v p="$pattern" '{if ($0~p && ! (NR % 2)) {print}}' file # even rows matching pattern
    

    then, to print the line following the match, modify the expressions to:

    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {f=1}}' file # lines after odd rows matching pattern
    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {f=1}}' file # lines after even rows matching pattern
    

    this uses the solution outlined here to print the single line after each line that satisfies the conditions.


    $ cat file
    1
    2
    3
    4
    5
    
    $ pattern="3"
    
    # lines after odd rows matching pattern
    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {f=1}}' file 
    4
    
    # lines after even rows matching pattern
    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {f=1}}' file
    $ 
    
    $ pattern="4"
    
    # lines after odd rows matching pattern
    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {f=1}}' file
    $ 
    
    # lines after even rows matching pattern
    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {f=1}}' file 
    5
    

    To also print the line itself that matches, with behavior like grep -A1:

    $ pattern="3"
    
    # odd lines matching pattern and line following them
    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {print;f=1}}' file 
    3
    4
    
    # even lines after even rows matching pattern
    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {print;f=1}}' file 
    $ 
    
    $ pattern="4"
    # odd lines matching pattern and line following them
    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {print;f=1}}' file
    $ 
    
    # even lines after even rows matching pattern
    $ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {print;f=1}}' file
    4
    5