Remove x lines form top and y lines form bottom using AWK?

How to remove x lines form top and y lines form bottom.

This works, but like awk only

cat file | head -n-y | awk 'NR>(x-1)'

so remove last 3 lines and 5 first

cat file | head -n-3 | awk 'NR>4'

Instead of awk

This removes first 4 lines (4+1) and removes last 3 lines

head -n-3 file | tail -n +5

OR

tail -n +5 file | head -n -3

You have to add +1 to the tail part..

EDIT:

with single awk:)

awk -v top="$x" -v bottom="$y" 'NR > top{j++;if(j > bottom){j=1};if(A[j]){print A[j];A[j]=$0}else{A[j]=$0}}' file
1 Like
## NAME: topntail
## USAGE: topntail [-b N] [-e N] [FILE ...]

b=1  ## No. of lines to remove from beginning
e=1  ## No. of lines to remove from end

## Parse command-line options
while getopts b:e: opt
do
  case $opt in
      b) b=$OPTARG ;;  ## Number of lines to remove from beginning
      e) e=$OPTARG ;;  ## Number of lines to remove from end
  esac
done
shift $(( $OPTIND - 1 ))

case $b$e in   ## check for non-numeric characters in $b and $e
    *[!0-9]*) exit 5 ;;
esac

if [ $e -eq 0 ]
then
  sed "1,${b}d" "$@"  ## just remove from the top
else
  ## The buf[] array is a rotating buffer which contains the last N lines
  ## where N is the number of lines to be removed from the bottom of the file
  ## Printing starts when the line number is equal to the sum of the number
  ## of lines to be removed from top and bottom, and continues to the end
  ## of the file; the earliest line in the buffer is printed.
  ## The last N lines will not be printed.
  awk 'NR > b + e { print buf[ NR % e ] }
                  { buf[ NR % e ] = $0 }' b=$b e=$e "$@"
fi
1 Like

Awk version:

awk 'NR>y+x{print A[NR%y]} {A[NR%y]=$0}' x=5 y=3 file

---
EDIT: OK I see the exact same solution is already part of cfajohnsons script, my bad...

Last few lines of cfajohnson's post present a similar awk solution, right?

Yes, we crossposted, I acknowledged that..