Bash:执行前突出显示命令(set -x)

For*_*vin 7 linux bash shell sh

我有一个 bash 脚本,它执行大约 20 个命令,出于调试目的,我发现自己经常滚动输出。\n不幸的是 bash 没有告诉我输出的哪一部分是哪个命令的一部分。\n当我在脚本中使用“set -x”时,它至少会打印一些有关其刚刚执行的信息,但我不太喜欢它生成的输出。

\n\n

例如,如果我有这个脚本:

\n\n
#!/bin/bash\n\nset -x\necho "foo"\nif [ "$ASD" == "QWE" ] ; then\n    echo "bar"\nfi\n
Run Code Online (Sandbox Code Playgroud)\n\n

我希望输出是这样的:

\n\n
\n

回显“foo”
\n foo
\n 回显“bar”
\n bar

\n
\n\n

或者可能:

\n\n
\n

echo "foo"
\n foo
\n if [ "value_of_ASD" == "QWE" ] ; 然后
\n echo "bar"
\n bar
\n fi

\n
\n\n

除了用粗体打印命令之外,用颜色突出显示也可以。但我不只是想在命令前面有“+”字符,而且我也不喜欢 if 语句像 那样显示\'[\' value_of_ASD == QWE \']\'

\n\n

我怎样才能用 bash 来实现这一点?

\n\n

目前输出看起来像这样:

\n\n
+ echo foo\nfoo\n+ \'[\' value_of_ASD == QWE \']\'\n+ echo bar\nbar\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑:

\n\n

我的一个想法是编写一个脚本,我将在主脚本的一开始就获取该脚本,然后让获取的脚本解析主脚本。像这样的东西:

\n\n

源_me.sh

\n\n
#!/bin/bash\nSCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/$(basename $0)"\nFORMAT_SET_BOLD=\'\\033[0;1m\'\nFORMAT_RESET=\'\\033[0m\'\n\ncat $SCRIPT_PATH | tail -n "+$START_LINE" | while read line; do\n    printf "${FORMAT_SET_BOLD}${line}${FORMAT_RESET}\\n"\n    eval "${line}"\ndone\n\nexit 0;\n
Run Code Online (Sandbox Code Playgroud)\n\n

主目录

\n\n
#!/bin/bash\nSTART_LINE=$((LINENO+1)) source ./source_me.sh\n\necho "Foo"\necho "Bar"\necho "+Hello"\n
Run Code Online (Sandbox Code Playgroud)\n\n

这种情况下的输出是:

\n\n
\n

echo "Foo"
\n Foo
\n echo "Bar"
\n Bar
\n echo "+Hello"
\n +Hello

\n
\n\n

但如果我使用跨多行的更复杂的代码(if 语句、循环等),此方法将会失败:

\n\n
#!/bin/bash\nSTART_LINE=$((LINENO+1)) source ./source_me.sh\n\necho "Foo"\n\nif [ "$FOOBAR" == "" ] ; then\n    echo "Bar"\nfi\n\necho "+Hello"\n
Run Code Online (Sandbox Code Playgroud)\n\n

在这种情况下我得到:

\n\n
\n

echo "Foo"
\n Foo

\n\n

if [ "$FOOBAR" == "" ] ; 然后
\n ./source_me.sh: eval: 第 9 行:语法错误:意外的文件结尾
\n echo "Bar"
\n Bar
\n fi
\n ./source_me.sh: eval: 第 8 行:语法错误接近意外标记 \xc2\xb4fi\'
\n ./source_me.sh: eval: 第 8 行:\xc2\xb4fi\'

\n\n

echo "+你好"
\n +你好

\n
\n

Gre*_*cki 10

我想用一些我认为值得单独回答的例子来扩展rubo77 的答案:

纯文本前缀

所以基本的例子是设置PS4一些纯文本,例如:

PS4="# "; set -x
Run Code Online (Sandbox Code Playgroud)

这将导致:



颜色和额外行文本前缀

但是,由于您可以使用特殊字符和 ANSI 转义码,因此您可以在每个新命令之前添加一个新行并以颜色打印前缀,例如:

PS4="\n\033[1;33m>>>\033[0m "; set -x
Run Code Online (Sandbox Code Playgroud)

结果:



动态颜色前缀

最后,您可以使命令前缀每次使用时调用其他程序,您可以使用它来添加时间戳,例如:

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

结果:


Pau*_*ges 0

您正在寻找的是set -v.

-v 打印出解释器刚刚读取的行。

-x 打印解释器刚刚读取的行的解析后结果。

文件x

set -vx
foo=1
echo $foo
set +vx
Run Code Online (Sandbox Code Playgroud)

执行:

$: . x
foo=1
++ foo=1
echo $foo
++ echo 1
1
set +vx
++ set +vx
Run Code Online (Sandbox Code Playgroud)