help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] Hook for `set -v`


From: Greg Wooledge
Subject: Re: [Help-bash] Hook for `set -v`
Date: Wed, 10 Jun 2015 16:20:41 -0400
User-agent: Mutt/1.4.2.3i

On Wed, Jun 10, 2015 at 03:00:29PM -0500, Peng Yu wrote:
> I want to highlight everything of the original lines printed via set -v.

So, let me get this straight:

You want to run a script.  With set -v in effect.  Which means you get
the script's output, and set -v's output, intermixed together.

You want to be able to separate them, or identify which line came from
where.

The manual does not list ANY details about how set -v works.  It literally
says only, "Print shell input lines as they are read."  No idea whether
that means print on stdout, print on stderr, etc.

So, let's assume you have NO control over what set -v does.

You DO have control over what the script does.

You could highlight the script's output instead.  Or redirect the script's
output to a file, etc.  That would give you the ability to see which line
of output came from where.

I still have no clue why you think set -v's output is useful in any way.


So, let's run a little test.  Here's a script:

imadev:~$ cat foo
#!/bin/bash -v

foo() {
  echo "$1 bottles of beer on the wall"
}
for ((i=5; i; i--)); do
  foo "$i"
done

Let's run it:

imadev:~$ ./foo
#!/bin/bash -v

foo() {
  echo "$1 bottles of beer on the wall"
}
for ((i=5; i; i--)); do
  foo "$i"
done
5 bottles of beer on the wall
4 bottles of beer on the wall
3 bottles of beer on the wall
2 bottles of beer on the wall
1 bottles of beer on the wall

As I said earlier, it reads the function definition, then reads the loop,
each of which produces a blob of set -v output; then it runs the loop
without any further set -v output.


Now let's see if we can figure out where set -v's output actually went.
Is it stderr?

imadev:~$ ./foo 2>/dev/null
5 bottles of beer on the wall
4 bottles of beer on the wall
3 bottles of beer on the wall
2 bottles of beer on the wall
1 bottles of beer on the wall

Yes!  It is stderr.

So, if you want to highlight only the set -v output, you can attach a
filter to stderr.  (And make sure nothing else writes to stderr.)

For example,

imadev:~$ cat foo
#!/bin/bash -v

exec 2> >(
  red=$(tput setaf 1) norm=$(tput sgr0)
  while read -r; do echo "$red$REPLY$norm"; done >&2
)

foo() {
  echo "$1 bottles of beer on the wall"
}
for ((i=5; i; i--)); do
  foo "$i"
done

sleep 1

And, running it:

imadev:~$ ./foo
#!/bin/bash -v

exec 2> >(
  red=$(tput setaf 1) norm=$(tput sgr0)
  while read -r; do echo "$red$REPLY$norm"; done >&2
)

  red=$(tput setaf 1) norm=$(tput sgr0)
tput setaf 1
5 bottles of beer on the wall
4 bottles of beer on the wall
3 bottles of beer on the wall
2 bottles of beer on the wall
1 bottles of beer on the wall
tput sgr0
  while read -r; do echo "$red$REPLY$norm"; done >&2

foo() {
  echo "$1 bottles of beer on the wall"
}
for ((i=5; i; i--)); do
  foo "$i"
done

sleep 1


There you go.  Now the set -v output (which appears whenever the
background filter job gets around to writing it) is red.  Useless,
but red.  Well, other than the initial setup before the filter is
finished loading.  That part's still unfiltered, because hey, chicken
and egg.  (You could filter stderr externally to work around that.)

Another approach would be to leave stderr unfiltered, and filter stdout
instead.

One of these days someone is going to ask a question that actually
contains a sensible statement of desired outcome, and that actually
makes sense to do in bash, and I am going to die of shock.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]