我今天参加了一个bash速成课程。
这是一个bash函数returns a value,通过echo:
#!/bin/bash
get_hello_name() {
echo 'Hello $1!'
}
msg=$(get_hello_name "x")
echo $msg
输出:
$ bash ./initial_script5.sh
Hello $1!
然后我错误地认为返回了 last echo(我来自Java和Python),并且正在尝试使用echo来调试函数的其余部分。
然后我想知道为什么尽管在this question中尝试了每一个建议,我仍然无法在echo语句中打印换行符。
此脚本演示了此问题:
#!/bin/bash
a_function() {
echo "---In function"
printf %"s\n" hello world
printf "Hello\nworld"
echo $'hello\nworld'
echo -e 'hello\nworld'
}
echo "---Pre function"
printf %"s\n" hello world
printf "Hello\nworld"
echo $'hello\nworld'
echo -e 'hello\nworld'
x=$(a_function "x")
echo $x
echo "---Post function"
printf %"s\n" hello world
printf "Hello\nworld"
echo $'hello\nworld'
echo -e 'hello\nworld'
$ 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
问题是函数中回声的所有连接在一起,在单独修剪后,然后作为一个整体返回。
所以这引出了两个问题:如何调试返回值的函数,以及如何将换行添加到变量上(不是我甚至想要做后者,但我想了解它)?
答案 0 :(得分:7)
新行实际上保留在变量中。它们不显示,因为echo
语句中的变量未包含在双引号中。从代码:
echo $x
使用不带双引号的变量时,会执行分词。在默认的$IFS
(wiki entry on IFS)下,这意味着所有空白集合(包括换行符和制表符)都将替换为单个空格。
为避免这种情况,只需使用双引号,如下所示:
echo "$x"
通过这一次更改,脚本的输出变为:
$ 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
中始终存在的换行符。
请注意,组合worldhello
出现在一行上,因为这是代码要求的内容:
printf "Hello\nworld"
echo $'hello\nworld'
printf
后world
不会打印换行符。因此,world
与后面的hello
显示在同一行。
man bash
解释双引号会抑制单词分裂:
如果替换出现在双引号内,则不会对结果执行分词和路径名扩展。
在变量扩展命令之后发生分词 替换和算术扩展:
shell扫描参数扩展命令的结果 替换和未发生的算术扩展 用于分词的双引号。
另一个微妙之处在于,只有在进行了一些替换时才会执行分词:
请注意,如果没有发生扩展,则不执行拆分。
通常,在执行单词拆分时,所有空格,制表符和换行符都将替换为单个空格。可以通过更改IFS
变量的值来更改此默认行为:
shell将IFS的每个字符视为分隔符,并将其拆分 其他扩展成为这些字符的单词的结果。如果 IFS未设置,或者它的值正好是 默认,然后是空格,制表符和换行符的序列 以前扩展的结果的开始和结束 忽略,任何IFS字符序列不在开头或 结尾用于划分单词。如果IFS的值不是 默认情况下,然后是空白字符空格和制表符的序列 在这个词的开头和结尾都被忽略了,只要 空白字符是IFS的值(IFS空格 字符)。 IFS中的任何字符都不是IFS空格 使用任何相邻的IFS空白字符,分隔字段。一个 IFS空白字符序列也被视为分隔符。如果IFS的值为null,则不会发生分词。
使用set -x
将行set -x
放在要运行的代码的开头。评估每一行的结果将在函数运行时显示,每个都以PS4
(默认为+
,空格)开头,以区别于正常输出。
可以通过包含行set +x
来关闭调试输出。
set -x
和set +x
也适用于命令行。
使用stderr
将调试输出发送到stderr
(文件描述符2),如下所示:
echo "My Debug Info" >&2
默认情况下,管道和命令替换仅在stderr
上运行。因此,默认情况下,发送到stderr
的信息将显示在终端上。
echo
默认情况下,echo
会忽略转义字符,序列\n
只表示\
后跟n
:
$ echo "Hello\nworld 4"
Hello\nworld 4
要将\n
解释为换行符,请使用-e
:
$ echo -e "Hello\nworld 4"
Hello
world 4
答案 1 :(得分:0)
遵循John1024提示后的工作代码(注意由于e
选项,新行打印在“1”行,但不是“4”:
#!/bin/bash
a_function() {
echo -e "Hello\nworld\n 1"
echo "Hello"
echo "world"
echo "Hello\nworld 4"
}
echo -e "Hello\nworld\n 1"
echo "Hello"
echo "world"
echo "Hello\nworld 4"
x=$(a_function "x")
echo "x-no-quotes>"
echo $x #No new lines!
echo "<x-no-quotes"
echo "x-in-double-quotes>"
echo "$x" #Yes new lines!
echo "<x-in-double-quotes"
echo -e "Hello\nworld\n 1"
echo "Hello"
echo "world"
echo "Hello\nworld 4"
输出:
Hello
world
1
Hello
world
Hello\nworld 4
x-no-quotes>
Hello world 1 Hello world Hello\nworld 4
<x-no-quotes
x-in-double-quotes>
Hello
world
1
Hello
world
Hello\nworld 4
<x-in-double-quotes
Hello
world
1
Hello
world
Hello\nworld 4
答案 2 :(得分:0)
你可能想用双引号来调用它
echo "$x"
但是,如果您想要明确显示您键入的内容,也称为文字表达式,请使用单引号echo '$x'