2

If I have a subshell command:

output="$(runfoo)";

is there way to store only the last line of the output from runfoo into the variable output? Or perhaps only the first line?

  • Simple first line (without extra child processes) would be `read -r output < <(runfoo)` - not so simple to use `read` to get the last line though. – cdarke Mar 04 '18 at 08:14
  • I think we have an answer from Cyrus –  Mar 04 '18 at 08:15
  • I know, I see it as a challenge to get an answer without using external programs. – cdarke Mar 04 '18 at 08:15
  • humma you consider head/tail external programs? –  Mar 04 '18 at 08:17
  • 1
    There *are* external programs, they are not part of any shell. Do a `type echo` (shell builtin, part of the shell) then a `type head` or `type tail`. – cdarke Mar 04 '18 at 20:54
  • Well I guess, but they are more built-in than some user-land bash function –  Mar 05 '18 at 01:52
  • Really? What leads you to that conclusion? There are a lot of builtins, but common commands, like `cat`, `ls`, `grep`, `cut`, `basename`, are external programs that carry an overhead and are often used unnecessarily. I'm not saying never use those programs, simplicity is often a good justification - the answer by @Cyrus is an example - but it is a test of skill to avoid them. – cdarke Mar 05 '18 at 07:30
  • See also http://porkmail.org/era/unix/award.html – cdarke Mar 05 '18 at 07:33
  • Hmmm, I would guess that those programs you just named are POSIX standards or whatever, like standardized stuff that's proven to work etc –  Mar 05 '18 at 19:41
  • @cdarke if you want to add an answer w/o using the tail/head commands, I will upvote, please consider upvoting the question as well lulz –  Mar 05 '18 at 19:42
  • By your comments I think you misunderstand what I was trying to do. The phrase "built-in" has a specific meaning with a shell. It means that the command is part of the shell binary and runs in the same process. You use the term *command* for `head(1)` and `tail(1)`. That's correct, but remember that these are *programs* whereas `echo`, `read` and `cd` (for example) are not. – cdarke Mar 05 '18 at 20:20

2 Answers2

6

Only stdout:

output="$(runfoo | tail -n 1)"

output="$(runfoo | head -n 1)"

Stdout and stderr:

output="$(runfoo 2>&1 | tail -n 1)"

output="$(runfoo 2>&1 | head -n 1)"
Cyrus
  • 84,225
  • 14
  • 89
  • 153
0

With bash

IFS=$'\n' output=$(inter=($(runfoo))
printf '%s\n' "${inter[0]}" "${inter[((${#inter[@]}-1))]}")
echo "$output"

runfoo return a multiline result like that :

first aaa

xcv

pattern3 a

bbb

last qqq

inter is a array (inter for intermediary)

inter=($(runfoo)) get the result of the runfoo command '$(runfoo)' in the array inter=($(...))

This way,

inter[0]=first

inter[1]=aaa

inter[6]=bbb

because IFS= whitespace tab or newline

So setting IFS to newline at the start

Each item of the array inter is a line of text

inter[0]=first aaa

inter[2]=pattern 3

output=$(create a array and print the first and the last item of this array)

So echo "$output"

first aaa

last qqq

Hope this help.

ctac_
  • 2,413
  • 2
  • 7
  • 17
  • can you explain in English what your command is doing? not sure sure what the `inter` command is, never heard of it –  Mar 05 '18 at 19:43
  • @OlegzandrDenman updated the answer with try of explain in English – ctac_ Mar 05 '18 at 20:50