我编写了一个脚本,用于收集本地计算机上的应用程序日志,然后从远程计算机上收集应用程序日志。
它有一个变量oldlogsdate
,可以读取我想要收集的日志的日期。
例如,如果我输入Apr 23
它工作正常,因为只有一个空格,但如果我输入(和Apr 4
之间有两个空格)它将删除一个空格。Apr
4
注意:这oldlogsdate
也是在用户的远程机器上设置的.bash_profile
,然后使用命令更改输入的日期sed
。
printf "\n";read -p "Which Date Logs you want to collect = " oldlogsdate
ssh -qt [email protected] "sed -i "s/oldlogsdate=.*/oldlogsdate=\'\"$oldlogsdate\"\'/" ~/.bash_profile"
oldlogsdate="Apr 7"
现在我为什么要使用它Apr 23
,Apr 4
它是命令的一部分ls
。
有没有办法在读取命令中保留双空格,或者其他更好的方法?
答案1
请注意您的命令行,即发送到另一端的命令ssh
部分:sed
ssh ... "sed -i "s/oldlogsdate=.*/oldlogsdate=\'\"$oldlogsdate\"\'/" ~/.bash_profile"
^^^^^^^^^..................................................^^^^^^^^^^^^^^^^^^
这里有两个带引号的字符串,标有^
.中间剩下的就是不是引用,其中包括变量扩展$oldlogsdate
。由于它没有被引用,所以它受到分词,并Apr 7
变成两个单词Apr
and 7
。也可以看看:什么时候需要双引号?
现在,ssh
它足够聪明,可以将它们重新粘在一起,但现在原始的空白量已经丢失,而只是添加了一个空格。
这有点类似于 shell 如何忘记其中的原始空白量并将echo
单词与单个空格粘合在一起:
$ echo hello world
hello world
但请注意,对于 SSH,单层引号没有帮助,因为 SSH 将命令行传递给远程端的 shell 进行解释,并且在该 shell 中,单词之间的额外空格也会丢失。
所以这仍然不起作用:
$ ssh localhost echo "hello world"
hello world
(本地 shell 删除引号,ssh
获取echo
和hello world
,然后传递到远程echo hello world
,其工作方式如上。)
实际上我们必须对两端进行引用以保持字符串完整:
$ ssh localhost 'echo "hello world"'
hello world
实际上,最好使用printf ":%s\n" hello world
etc.来更正确地显示断词的位置,但结果是相似的。
切换引号以使双引号位于最外层,让本地 shell 扩展变量,并为远程 shell 保留单引号,从而最大程度地减少扩展量。您仍然需要对要发送到另一端的任何双引号进行反斜杠转义。
$ greeting="hello world"
$ ssh localhost "echo '$greeting'"
hello world
只要变量本身不包含单引号,就应该可以工作。如果是这样,事情会变得更难看,请参阅:转义变量以用作另一个脚本的内容
我认为命令行@萨莎的回答看起来它应该适合你的情况。
另请参阅,例如这个问题:在 ssh $host $FOO 和 ssh $host "sudo su user -c $FOO" 类型构造中引用 手头的问题有一个更多的处理层,但答案似乎也适用于“更简单”的情况。
答案2
读取命令删除双空格并仅保留一个
事实并非如此。该read
命令本身保持内部空白不变(但是,除非您设置IFS
为空,否则它将修剪前导和尾随空白;如果您不使用,它还会损坏反斜杠-r
)。
read myVar <<<'Apr 4'
echo "$myVar" # will output: Apr 4
那就是你因为没有双引号变量而丢失了空格:
myVar2='Apr 4'
echo $myVar2 # will mangle spaces, please always use "$myVar2" instead
不正确引用变量不仅会使脚本行为异常,还可能引入潜在的安全风险。
一点点更正确的命令是
ssh -qt [email protected] "sed -i 's/oldlogsdate=.*/oldlogsdate=\"$oldlogsdate\"/' ~/.bash_profile"
但它并不通用,而且也不安全,因为它没有考虑到该$oldlogsdate
值不仅可能包含空格,还可能包含撇号、斜杠、反斜杠、美元符号和感叹号。