在shell脚本中,冒号(:)被视为变量创建的运算符

时间:2018-07-05 08:53:36

标签: bash shell

我有以下代码段:

host="https://example.com"
port="80"
url="${host}:${port}"
echo $url

输出为:

:80ps://example.com

我如何在这里逃脱结肠。我也尝试过:

url="${host}\:${port}"

但是它不起作用。 预期输出为:

https://example.com:80

2 个答案:

答案 0 :(得分:0)

它对我有用,请尝试删除变量中的回车,然后尝试。

new_host=$(echo "$host" |  tr -d '\r')
new_port=$(echo "$port" |  tr -d '\r')
new_url="${new_host}:${new_port}"

答案 1 :(得分:0)

您很可能遇到了我所说的 Linefeed-Limbo 。 如果我复制了您从StackOverflow提供的代码并在我的计算机上运行(bash版本4.4.19(1)),则它可以正确输出

user@host:~$ cat script.sh
host="https://example.com"
port="80"
url="${host}:${port}"
echo $url

user@host:~$ bash script.sh
https://example.com:80

什么是Linefeed-Limbo?

不同的操作系统使用不同的ASCII符号来表示何时在文本(例如脚本)中出现换行。该Wikipedia article提供了很好的介绍。

如您所见,Unix和类Unix系统使用单个字符\n,也称为“换行”。 Windows和其他系统都使用\r\n,因此先使用“回车”,再使用“换行”。

现在发生的是,当您在Windows上用记事本之类的编辑器编写脚本时,您写的是host="example.com"\r\n。当您将此文件复制到Linux时,Linux会将\r解释为脚本的一部分,因为只有\n被视为换行符。的确,当我将换行符样式更改为DOS样式时,我将获得准确的输出。

我该如何解决?

您可以通过多种方法解决此问题。

转换脚本(使用dos2unix

由于您要做的只是将\r\n的每个实例替换为\n,因此您可以使用所需的任何文本编辑软件。但是,如果您喜欢简单的解决方案,那么dos2unix(及其姊妹unix2dos)可能就是您想要的:

user@host:~$ dos2unix script.sh
dos2unix: converting file script.sh to Unix format...

就是这样。立即运行文件,您会发现它运行良好。

正确编码源文件

通过使用更高级的文本编辑器(例如Notepad++),您可以定义要使用的换行样式。

Notepad++ in CRLF-mode Notepad++ in LF-mode

通过将换行符类型更改为要在其上运行脚本的任何系统,您将再也不会遇到这样的问题。

回合奖励:为什么输出:80ps://example.com

要了解您的输出为何如此,您必须查看脚本的工作以及\r的含义。

尝试将您的终端机视为老式打字机。返回笔架意味着您再次开始在左侧书写。进行“换行”是指滑动纸张。这两件事是分开的,我认为这就是为什么某些系统决定将这两个字符用作逻辑“换行符”的原因。

但是我离题了。让我们看第一行host="https://example.com"\r。 打印时的意思是“打印https://example.com,然后将笔架放回起点”。然后,当您打印:80\r时,它不会在“ .com”之后开始,而是从行的开头开始,因为(您不知不觉地)告诉了光标该行。然后它忽略了前几​​个字符,导致写入“:80ps://example.com”。请记住,在80之后,您再次放置了回车符,因此,您要编写的任何新文本最终都会再次覆盖开头。