如何调试返回值的 Bash 函数,以及如何向变量添加换行符? [英] How can I debug a Bash function that returns a value, and how can I add newlines to a variable?

查看:27
本文介绍了如何调试返回值的 Bash 函数,以及如何向变量添加换行符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个 Bash 函数,它返回一个值,通过回声:

This is a Bash function that returns a value, via echo:

#!/bin/bash
get_hello_name() {
  echo 'Hello $1!'
}
msg=$(get_hello_name "x")
echo $msg

输出:

$ bash ./initial_script5.sh
Hello $1!

然后我错误地认为 last 回声已返回(我来自 JavaPython),并且正在尝试使用 echo 调试函数的其余部分.

I then incorrectly thought that the last echo was returned (I come from Java and Python), and was trying to use echo to debug the rest of the function.

然后我想知道为什么我无法在我的 echo 语句中打印出换行符,尽管在 这个问题.

And then I was wondering why the heck I could not print out newlines in my echo statements, despite trying every single suggestion in this question.

这个脚本演示了这个问题:

This script demonstrates the problem:

#!/bin/bash
a_function() {
  echo "---In function"

  printf %"s
" hello world
  printf "Hello
world"
  echo $'hello
world'
  echo -e 'hello
world'
}

echo "---Pre function"
printf %"s
" hello world
printf "Hello
world"
echo $'hello
world'
echo -e 'hello
world'

x=$(a_function "x")
echo $x

echo "---Post function"
printf %"s
" hello world
printf "Hello
world"
echo $'hello
world'
echo -e 'hello
world'


$ bash ./initial_script5.sh
---Pre function
hello
world
Hello
worldhello
world
hello
world
---In function hello world Hello worldhello world hello world
---Post function
hello
world
Hello
worldhello
world
hello
world

问题在于函数中的所有回声都连接在一起,在单独修剪后,然后作为一个整体返回.

The problem is that all of the echos in the function are concatenated together, after being individually trimmed, and then returned as a whole.

所以这让我想到了两个问题:如何调试返回值的函数,以及如何将换行符附加到变量上(并不是说我什至想要做后者,但我想了解它)?

So this leads me to two questions: How do you debug a function that returns a value, and how do you append newlines onto a variable (not that I even want to do the latter, necessarily, but I would like to understand it)?

推荐答案

为什么换行符似乎从变量中消失了

换行符实际上保留在变量中.它们不会显示,因为 echo 语句中的变量没有用双引号括起来.来自代码:

Why the newlines seemed to disappear from the variable

The newlines are actually retained in the variable. They do not display because the variable in the echo statement is not enclosed in double-quotes. From the code:

echo $x

当使用没有双引号的变量时,会执行分词.在默认的 $IFS(IFS 上的维基条目)下,这个意味着所有空格集合,包括换行符和制表符,都被替换为单个空格.

When using a variable without double-quotes, word splitting is performed. Under the default $IFS (wiki entry on IFS), this means that all collections of whitespace, including newlines and tabs, are replaced with single space.

为避免这种情况,只需使用双引号,如下所示:

To avoid that, simply use double quotes as in:

echo "$x"

通过这个单一的改变,你的脚本输出变成:

With that single change, the output of your script becomes:

$ bash a,sh 
---Pre function
hello
world
Hello
worldhello
world
hello
world
---In function
hello
world
Hello
worldhello
world
hello
world
---Post function
hello
world
Hello
worldhello
world
hello
world

现在显示变量 x 中的换行符.

The newlines that were always in the variable x are now displayed.

注意组合 worldhello 出现在一行中,因为这是代码要求的:

Note that the combination worldhello appears on one line because because that is what the code asked for:

printf "Hello
world"
echo $'hello
world'

printf 不会在 world 之后打印换行符.因此,该 world 与后面的 hello 出现在同一行.

The printf does not print a newline after world. Hence, that world appears on the same line as the hello which follows.

man bash 解释双引号禁止分词:

man bash explains that double-quotes inhibit word splitting:

如果替换出现在双引号内,则不会对结果进行分词和路径扩展.

If the substitution appears within double quotes, word splitting and pathname expansion are not performed on the results.

分词发生在之后变量扩展,命令替换和算术扩展:

Word-splitting happens after variable expansion, command substitution, and arithmetic expansion:

shell 扫描参数扩展的结果,命令替换和算术扩展没有发生在用于分词的双引号.

The shell scans the results of parameter expansion, command substitution, and arithmetic expansion that did not occur within double quotes for word splitting.

另一个微妙之处在于,只有在发生某些替换时才执行分词:

Another subtlety is that word splitting is performed only if some substitution took place:

请注意,如果没有发生扩展,则不会进行拆分.

Note that if no expansion occurs, no splitting is performed.

通常情况下,进行分词时,空格、制表符和换行符的所有字符串都将替换为单个空格.可以通过更改 IFS 变量的值来更改此默认行为:

Normally, when word splitting is performed, all strings of spaces, tabs, and newlines are replaced by a single space. This default behavior can be changed by changing the value of the IFS variable:

shell 将 IFS 的每个字符都当作一个分隔符,并将其他扩展为这些字符的单词的结果.如果IFS 未设置,或者它的值正好是 ,默认,然后是空格、制表符和换行符的序列先前扩展结果的开始和结束是忽略,以及任何不在开头或开头的 IFS 字符序列end 用于分隔单词.如果 IFS 的值不是默认,然后空格字符 space 和 tab 的序列是忽略单词的开头和结尾,只要空格字符在 IFS 的值中(一个 IFS 空格特点).IFS 中不是 IFS 空格的任何字符,以及与任何相邻的 IFS 空白字符,分隔一个字段.一个IFS 空白字符序列也被视为分隔符.如果IFS的值为空,则不发生分词.

The shell treats each character of IFS as a delimiter, and splits the results of the other expansions into words on these characters. If IFS is unset, or its value is exactly , the default, then sequences of space, tab, and newline at the beginning and end of the results of the previous expansions are ignored, and any sequence of IFS characters not at the beginning or end serves to delimit words. If IFS has a value other than the default, then sequences of the whitespace characters space and tab are ignored at the beginning and end of the word, as long as the whitespace character is in the value of IFS (an IFS whitespace character). Any character in IFS that is not IFS whitespace, along with any adjacent IFS whitespace characters, delimits a field. A sequence of IFS whitespace characters is also treated as a delimiter. If the value of IFS is null, no word splitting occurs.

如何调试

  1. 使用set -x

将行 set -x 放在要运行的代码的开头.函数运行时会显示每一行的求值结果,每行前面都有PS4(默认为+,空格)以区别于正常输出.

Place the line set -x at the beginning of the code that you wish to run. The results of evaluating each line will be displayed as the function is run, each preceded by PS4 (default is +, space) to distinguish it from normal output.

可以通过包含行 set +x 来关闭调试输出.

The debug output can be turned off by including the line set +x.

set -xset +x 都可以在命令行上使用.

set -x and set +x both also work on the command line.

使用stderr

将调试输出发送到 stderr(文件描述符 2),如下所示:

Send debug output to stderr (file descriptor 2) as follows:

echo "My Debug Info" >&2

默认情况下,管道和命令替换仅在 stderr 上运行.因此,发送到 stderr 的信息将默认显示在终端上.

By default, pipelines and command substitutions only operate on stderr. Consequently, information sent to stderr will, by default, appear on the terminal.

更多关于 echo

默认情况下,echo 忽略转义字符,序列 仅表示 后跟一个 n:

More on echo

By default, echo ignores escape characters and the sequence simply means a followed by an n:

$ echo "Hello
world 4"
Hello
world 4

要将 解释为换行符,请使用 -e:

To have interpreted as a newline, use -e:

$ echo -e "Hello
world 4"
Hello
world 4

这篇关于如何调试返回值的 Bash 函数,以及如何向变量添加换行符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆