I have text file. Task – get first and last line from file after
$ cat file | grep -E "1|2|3|4" | commandtoprint $ cat file 1 2 3 4 5
Need this without cat output (only 1 and 5).
~$ cat file | tee >(head -n 1) >(wc -l) 1 2 3 4 5 5 1
Maybe awk and more shorter solution exist…
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
sed Solution:
sed -e 1b -e '$!d' file
When reading from stdin if would look like this (for example 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 & tail Solution:
(head -n1 && tail -n1) <file
When data is coming from a command (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 Solution:
awk 'NR==1; END{print}' file
And also the piped example with 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}
Method 2
sed -n '1p;$p' file.txt will print 1st and last line of file.txt .
Method 3
A funny pure Bash≥4 way:
cb() { (($1-1>0)) && unset "ary[$1-1]"; }
mapfile -t -C cb -c 1 ary < file
After this, you’ll have an array ary with first field (i.e., with index 0) being the first line of file, and its last field being the last line of file. The callback cb (optional if you want to slurp all lines in the array) unsets all the intermediate lines so as to not clutter memory. As a free by-product, you’ll also have the number of lines in the file (as the last index of the array+1).
Demo:
$ mapfile -t -C cb -c 1 ary < <(printf '%sn' {a..z})
$ declare -p ary
declare -a ary='([0]="a" [25]="z")'
$ # With only one line
$ mapfile -t -C cb -c 1 ary < <(printf '%sn' "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='()'
Method 4
With sed you could delete lines if NOT the 1st one AND NOT the la$t one.
Use ! to NOT (negate) a condition and the X{Y..} construct to combine X AND Y conditions:
cmd | sed '1!{$!d;}'
or you could use a range – from 2nd to la$t – and delete all lines in that range except the la$t line:
cmd | sed '2,${$!d;}'
Method 5
Using Perl:
$ seq 10 | perl -ne 'print if 1..1 or eof' 1 10
The above prints the first item in the output of seq 10 via the if 1..1, while the or eof will also print the last item.
Method 6
Without cat:
$ cat file |tee >(head -n1) >(tail -n1) >/dev/null 1 5
or
$ (head -n1 file;tail -n1 file) 1 5
Method 7
$ seq 100 | { IFS= read -r first; echo "$first"; tail -1; }
1
100
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0