到底是怎么回事

到底是怎么回事

我试图echo在 Puppet 规则内部使用向 中添加一行.bashrc,但我似乎无法正确引用。

'/usr/bin/echo -E PS1=\"[\t--------------------------------------------------------\n-\u@\h:\W]\$\" >> /home/unu/.bashrc'

这件事给了我以下结果:

PS1="[t--------------------------------------------------------n-u@h:W]$"

另一种尝试:

'/usr/bin/echo -E PS1="[\t--------------------------------------------------------\n-\u@\h:\W]\$" >> /home/unu/.bashrc'

这件事给了我以下内容:

PS1=[\t--------------------------------------------------------\n-\u@\h:\W]$

另一个:

'/usr/bin/echo -e PS1="[\\t--------------------------------------------------------\\n-\\u@\\h:\\W]\\$" >> /home/unu/.bashrc'

这个给了我这个:

PS1=[   --------------------------------------------------------
-\u@\h:\W]$

我似乎无法找到一种方法来做到这一点,而不需要\"某种方式进行解释。我该怎么做?

我想过使用更多引号,但这会导致 Puppet 出现语法错误:

"/usr/bin/echo -e 'PS1="[\\t--------------------------------------------------------\\n-\\u@\\h:\\W]\\$"' >> /home/unu/.bashrc"

得到这样的结果:

Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Syntax error at '' (file: /etc/puppetlabs/code/environments/production/modules/profile/manifests/ps1.pp, line: 3, column: 38) on node centoslave1

这是整个代码:

class profile::ps1 {
        exec { 'myps1':
        command => "/usr/bin/echo -e 'PS1="[\\t--------------------------------------------------------\\n-\\u@\\h:\\W]\\$"' >> /home/unu/.bashrc"
        }
}

答案1

到底是怎么回事

命令=>“/usr/bin/echo -e 'PS1=”[\\t-------------------------------------------- --------------------------\\n-\\u@\\h:\\W]\\$"' >> /主页/unu/.bashrc"

了解哪里出了问题是纠正错误的线索。元素的右侧(位于 之后=>)必须是字符串。字符串在 Puppet 中有多种形式。双引号字符串以双引号开头,以第二组结尾。所以你的字符串是

“/usr/bin/echo -e 'PS1=”
然后,您可以在其后添加对于清单而言语法不正确的乱码:

[\t------------------------------------------------------------ ---------\n-\u@\h:\W]\$
和另一个字符串:

“'>>/home/unu/.bashrc”

正确执行此操作

自下而上构建正确的设置。从您希望命令输出到该文件的内容开始。输出是一个 shell 命令,它将PS1shell 变量设置为:

[\t------------------------------------------------------------ ---------\n-\u@\h:\W]\$
这样的命令是,使用单引号(这里最好使用双引号,因为它不需要对那些\$字符进行转义)来阻止 shell 对转义序列进行转义:

PS1='[\t-------------------------------------------------------- ------------\n-\u@\h:\W]\$'
echo您可以通过 shell 调用来输出这样的命令(我们将返回到这一点),但是您需要通过更多转义来确保单引号到达echo命令:

echo PS1=\''[\t-------------------------------------------------------- ---------------\n-\u@\h:\W]\$'\'

然而,这存在问题,因为echo跨平台和 shell 没有一致的行为,并且(讽刺的是)它的可能的转义序列的转换实际上是不是你想要什么。事实上,尽管您的问题上有标签,但运行命令的 shell 不一定是 Bourne Again shell,具体取决于操作系统(您尚未指定)。例如,它可能是 Debian Almquist shell。为了获得更好的结果,请使用printf

printf "PS1='%s'\n" '[\t------------------------------------ ---------------------\n-\u@\h:\W]\$' >> /home/unu/.bashrc

请注意,到目前为止的假设是它是提供给 shell 执行的命令行。对传递给echo和的参数进行转义和引用printf,以便它们最终得到正确的内容,这是根据 shell 规则进行的。因此,请注意有关提供商的问题评论。

现在你需要编码在木偶弦中。单引号字符串在这里也是更好的选择,因为您只需要转义'\字符(这与单引号字符串的规则,注意):

命令 => 'printf "PS1=\'%s\'\\n" \'[\\t---------------------------------------- ------------------------------\\n-\\u@\\h:\\W]\\$\ ' >> /home/unu/.bashrc'

进一步阅读

答案2

(至少)有两个层面的因素会吞噬你的角色:

  1. 贝壳
  2. echo本身

如果你运行:

echo "hello, \"world\""

你得到输出

hello, "world"

因为贝壳吃了反斜杠处的双引号,而不是 echo。 shell 将它们视为 shell 语法,表示将其hello, "world"作为单个参数传递给 echo。然后打印回声,加上换行符。

echo -e特别是还解释反斜杠序列(取决于实现);解决这个问题的简单方法是使用printf '%s\n' WHATEVER代替echo WHATEVER.

在大多数情况下,您可以使用单引号保护某些内容免受 shell 的影响(只要它本身不包含单引号)。所以,您可能想要:

printf '%s\n' 'PS1="[\t--------------------------------------------------------\n-\u@\h:\W]\$"'

这使:

PS1="[\t--------------------------------------------------------\n-\u@\h:\W]\$"

如果您必须在多层 shell 转义中幸存下来,您可能会发现printf '%q\n' WHATEVER有用,它以一种在 shell 中幸存的格式打印它(但这可能是 Bash 独有的功能,尚未检查)。

顺便说一句:如果您需要保护单引号字符串中的单引号,则必须执行以下操作'\''

$ printf '%s\n' 'i'\''ll'
i'll

如果你仔细看的话,实际上是'i'++ 。\''ll'

PS:PS1经历了另一次扩展(请参阅 Bash 文档);你显然知道这些\u。但变量也会扩展——所以如果你在最后有一些东西$,你需要转义它(用如果在双引号字符串内则使用反斜杠):PS1="foo\\\$PATH % "

答案3

使用printf

printf '%s\n' 'PS1="[\t--------------------------------------------------------\n-\u@\h:\W]\$"' >> /home/unu/.bashrc

答案4

您可以简单地使用cat

cat /var/tmp/ps1-file >> /home/unu/.bashrc

可以手动创建(使用您喜欢的编辑器),这样您就可以避免//ps1-file中的转义问题。为了使该文件到达节点,您需要添加bashechoprintf文件部分。

file { "/var/tmp/ps1-file"
    source => 'puppet:///modules/bashrc/ps1'
}

这意味着将原始文件放在modulepath.由于其内容是少量文本,您可以用 指定它们content =>,但这会产生其自身的引用/转义问题。

相关内容