5
#!/bin/bash -x
echo This is a script that has debugging turned on

This script outputs

+ echo This is a script that has debugging turned on
This is a script that has debugging turned on

I want to get rid of these +'s by deleting them or replacing them. I expected sed could fix my problem (sed 's/^\++//g') -- But this approach doesn't affect the debug output lines.

With some more experimenting, I discovered that the debug output seems to be getting written to stderr (inferred this with the command ./test.sh 2>/dev/null which the output then excludes the debug lines)

With this new information, I would expect this to work ./test.sh 2>&1 | sed 's/^\++//g'

But, alas, I still get the same undesired output:

+ echo This is a script that has debugging turned on
This is a script that has debugging turned on
aitee
  • 53

3 Answers3

15

The + is the PS4 prompt. Set it to an empty string:

#!/bin/bash

PS4=''
set -x

echo 'This is a script that has debugging turned on'

Testing:

$ bash script.sh
echo 'This is a script that has debugging turned on'
This is a script that has debugging turned on

Or, with your original script, set PS4 to an empty string for the script when invoking it:

$ PS4='' ./script.sh
echo This is a script that has debugging turned on
This is a script that has debugging turned on

This could be used to insert a timestamp:

$ PS4='$(date +"%T: ")' ./script.sh
21:08:19: echo 'This is a script that has debugging turned on'
This is a script that has debugging turned on
21:08:19: echo 'Now sleeping for 2 seconds'
Now sleeping for 2 seconds
21:08:19: sleep 2
21:08:21: echo Done
Done
Kusalananda
  • 333,661
  • 1
    If you want to avoid the fork & exec during prompt evaluation you can use Bash’s extension to the built-in printf command: $(printf '%(%T)T: ' -1). – David Foerster Oct 24 '18 at 07:01
5

The main limitation you're running into is that + is an extended regular expression feature, so you'll need to enable extended regular expression functionality; with most seds, that's with the -E flag:

./test.sh 2>&1 | sed -E 's/^\++ //'

I made two other changes:

  • added a trailing space, so that debugged commands show up left-aligned
  • removed the /g flag, since the regex is anchored, there can be only one match per line
don_crissti
  • 82,805
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • Note that once you commingle stdout and stderr, any actual (stdout) output with leading plus signs will also be stripped. – Jeff Schaller Oct 23 '18 at 18:06
  • Yes. I realize this. With Kusalandanda's answer it will circumvent this problem. Although this discovery that it is coming over standard error is surprising. It may just be that fact rather than the +'s that is causing the root behavior I'm seeing. – aitee Oct 23 '18 at 21:07
4

You can redirect stderr into a process substitution. However that may affect the order of the output:

$ bash -x -c 'hostname; echo "$(date)"'
+ hostname
jackmanVM
++ date
+ echo 'Tue Oct 23 15:22:02 EDT 2018'
Tue Oct 23 15:22:02 EDT 2018

$ bash -x -c 'hostname; echo "$(date)"' 2> >(sed -E 's/^\++/debug: /')
debug:  hostname
jackmanVM
debug:  date
Tue Oct 23 15:22:35 EDT 2018
debug:  echo 'Tue Oct 23 15:22:35 EDT 2018'
glenn jackman
  • 85,964