Как прочитать первую и последнюю строку из вывода cat?

Как прочитать первую и последнюю строку из вывода cat?

У меня есть текстовый файл. Задача - получить первую и последнюю строку из файла после

$ cat file | grep -E "1|2|3|4" | commandtoprint

$ cat file
1
2
3
4
5

Это нужно без вывода cat (только 1 и 5).

~$ cat file | tee >(head -n 1) >(wc -l)
1
2
3
4
5
5
1

Может быть, существуют awk и более короткие решения...

решение1

седРешение:

sed -e 1b -e '$!d' file

При чтении из stdinif это будет выглядеть так (например ps -ef):

ps -ef | sed -e 1b -e '$!d'
UID        PID  PPID  C STIME TTY          TIME CMD
root      1931  1837  0 20:05 pts/0    00:00:00 sed -e 1b -e $!d

голова и хвостРешение:

(head -n1 && tail -n1) <file

Когда данные поступают из команды ( ps -ef):

ps -ef 2>&1 | (head -n1 && tail -n1)
UID        PID  PPID  C STIME TTY          TIME CMD
root      2068  1837  0 20:13 pts/0    00:00:00 -bash

awkРешение:

awk 'NR==1; END{print}' file

А также пример с конвейером ps -ef:

ps -ef | awk 'NR==1; END{print}'
UID        PID  PPID  C STIME TTY          TIME CMD
root      1935  1837  0 20:07 pts/0    00:00:00 awk NR==1; END{print}

решение2

sed -n '1p;$p' file.txtнапечатает первую и последнюю строку файла file.txt.

решение3

Забавный способ на чистом Bash≥4:

cb() { (($1-1>0)) && unset "ary[$1-1]"; }
mapfile -t -C cb -c 1 ary < file

После этого у вас будет массив aryс первым полем (т.е. с индексом 0), являющимся первой строкой file, и его последним полем, являющимся последней строкой file. Обратный вызов cb(необязательный, если вы хотите выжать все строки в массиве) отменяет все промежуточные строки, чтобы не загромождать память. В качестве бесплатного побочного продукта у вас также будет количество строк в файле (как последний индекс массива+1).

Демонстрация:

$ mapfile -t -C cb -c 1 ary < <(printf '%s\n' {a..z})
$ declare -p ary
declare -a ary='([0]="a" [25]="z")'
$ # With only one line
$ mapfile -t -C cb -c 1 ary < <(printf '%s\n' "only one line")
$ declare -p ary
declare -a ary='([0]="only one line")'
$ # With an empty file
$ mapfile -t -C cb -c 1 ary < <(:)
declare -a ary='()'

решение4

Без кота:

$ cat file |tee >(head -n1) >(tail -n1) >/dev/null
1
5

или

$ (head -n1 file;tail -n1 file)
1
5

Связанный контент