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\nRun Code Online (Sandbox Code Playgroud)\n\n我希望输出是这样的:
\n\n\n\n\n回显“foo”
\n
\n foo
\n 回显“bar”
\n bar
或者可能:
\n\n\n\n\necho "foo"
\n
\n foo
\n if [ "value_of_ASD" == "QWE" ] ; 然后
\n echo "bar"
\n bar
\n fi
除了用粗体打印命令之外,用颜色突出显示也可以。但我不只是想在命令前面有“+”字符,而且我也不喜欢 if 语句像 那样显示\'[\' value_of_ASD == QWE \']\'。
我怎样才能用 bash 来实现这一点?
\n\n目前输出看起来像这样:
\n\n+ echo foo\nfoo\n+ \'[\' value_of_ASD == QWE \']\'\n+ echo bar\nbar\nRun 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;\nRun 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"\nRun Code Online (Sandbox Code Playgroud)\n\n这种情况下的输出是:
\n\n\n\n\necho "Foo"
\n
\n Foo
\n echo "Bar"
\n Bar
\n echo "+Hello"
\n +Hello
但如果我使用跨多行的更复杂的代码(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"\nRun Code Online (Sandbox Code Playgroud)\n\n在这种情况下我得到:
\n\n\n\necho "Foo"
\n\n
\n Fooif [ "$FOOBAR" == "" ] ; 然后
\n\n
\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\'echo "+你好"
\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)
结果:
您正在寻找的是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)