Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash: highlight command before execution (set -x)

Tags:

linux

bash

shell

sh

I have a bash script which executes about 20 commands and for debugging purposes I find myself scrolling through the output a lot. Unfortunately bash doesn't tell me which part of the output is part of what command. When I use "set -x" in the script it at least prints some information on what it just executed, but I don't really like the output it generates.

For instance, if I have this script:

#!/bin/bash

set -x
echo "foo"
if [ "$ASD" == "QWE" ] ; then
    echo "bar"
fi

I would like the output to be something like this:

echo "foo"
foo
echo "bar"
bar

Or maybe:

echo "foo"
foo
if [ "value_of_ASD" == "QWE" ] ; then
echo "bar"
bar
fi

Instead of printing the commands in bold, highlighting with a color would also be okay. But I don't just want to have "+" characters in front of the commands and I also don't like the if statements showing up like '[' value_of_ASD == QWE ']'.

How can I accomplish that with bash?

At the moment the output looks like this btw:

+ echo foo
foo
+ '[' value_of_ASD == QWE ']'
+ echo bar
bar

Edit:

One idea I had was to write a script that I would source in the very beginning of the main script and then let the sourced script parse the main one. Something like this:

source_me.sh

#!/bin/bash
SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/$(basename $0)"
FORMAT_SET_BOLD='\033[0;1m'
FORMAT_RESET='\033[0m'

cat $SCRIPT_PATH | tail -n "+$START_LINE" | while read line; do
    printf "${FORMAT_SET_BOLD}${line}${FORMAT_RESET}\n"
    eval "${line}"
done

exit 0;

main.sh

#!/bin/bash
START_LINE=$((LINENO+1)) source ./source_me.sh

echo "Foo"
echo "Bar"
echo "+Hello"

The output in that case is:

echo "Foo"
Foo
echo "Bar"
Bar
echo "+Hello"
+Hello

But this method will fail if I use more complex code that goes over multiple lines (if statements, loops etc):

#!/bin/bash
START_LINE=$((LINENO+1)) source ./source_me.sh

echo "Foo"

if [ "$FOOBAR" == "" ] ; then
    echo "Bar"
fi

echo "+Hello"

In this case I get:

echo "Foo"
Foo

if [ "$FOOBAR" == "" ] ; then
./source_me.sh: eval: line 9: syntax error: unexpected end of file
echo "Bar"
Bar
fi
./source_me.sh: eval: line 8: syntax error near unexpected token ´fi'
./source_me.sh: eval: line 8: ´fi'

echo "+Hello"
+Hello

like image 522
Forivin Avatar asked May 13 '26 15:05

Forivin


1 Answers

I would like to extend rubo77's answer with a few examples that I think deserve a separate answer:

Plain text prefix

So the basic example is to set PS4 to some plain text, e.g.:

PS4="# "; set -x

Which will result in:



Color & extra line text prefix

But because you can use special characters and ANSI escape codes you can for example add a new line before each new command and print the prefix in a color, e.g.:

PS4="\n\033[1;33m>>>\033[0m "; set -x

Result:



Dynamic color prefix

Finally you can make the command prefix call other programs with each use, which you can use to add a timestamp, e.g.:

# yes, there have to be single quotes below, not double!
PS4='\033[1;34m$(date +%H:%M:%S)\033[0m '; set -x

Result:

like image 194
Greg Dubicki Avatar answered May 16 '26 07:05

Greg Dubicki



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!