【问题标题】:Printf splits a string at spaces using Bash [duplicate]Printf 使用 Bash 在空格处拆分字符串 [重复]
【发布时间】:2016-05-18 03:27:56
【问题描述】:

我在使用 bash 中的 printf 函数时遇到了一些问题。 我编写了一个小脚本,在上面传递了一个名称和两个字母(例如“sh”、“py”、“ht”),它在当前工作目录中创建了一个名为“name.extension”的文件。 例如,如果我执行seed test py,则会在当前工作目录中创建一个名为test.py 的文件,并使用shebang #!/usr/bin/python3

到目前为止,一切都很好,没什么特别的:我正在学习 shell 脚本,我认为这可能是一个简单的练习,可以测试到目前为止所获得的知识。 问题是当我想创建一个 HTML 文件时。这是我使用的功能:

creaHtml(){
        head='<!--DOCTYPE html-->\n<html>\n\t<head>\n\t\t<meta charset=\"UTF-8\">\n\t</head>\n\t<body>\n\t</body>\n</html>'
        percorso=$CARTELLA_CORRENTE/$NOME_FILE.html
        printf $head>>$percorso
        chmod 755 $percorso

}

如果我运行,例如,seed test ht 调用了正确的函数 (creaHtml),则会创建 test.html,但如果我尝试查看它,我只会看到:

<!--DOCTYPE

没有别的了。 这是该函数的跟踪:

[sviluppo:~/bin]$ seed test ht
+ creaHtml
+ head='<!--DOCTYPE html-->\n<html>\n\t<head>\n\t\t<meta charset=\"UTF-8\">\n\t</head>\n\t<body>\n\t</body>\n</html>'
+ percorso=/home/sviluppo/bin/test.html
+ printf '<!--DOCTYPE' 'html-->\n<html>\n\t<head>\n\t\t<meta' 'charset=\"UTF-8\">\n\t</head>\n\t<body>\n\t</body>\n</html>'
+ chmod 755 /home/sviluppo/bin/test.html
+ set +x

但是,如果我尝试从终端运行printf '&lt;!--DOCTYPE html--&gt;\n&lt;html&gt;\n\t&lt;head&gt;\n\t\t&lt;meta charset=\"UTF-8\"&gt;\n\t&lt;/head&gt;\n\t&lt;body&gt;\n\t&lt;/body&gt;\n&lt;/html&gt;',我会看到正确的输出:HTML 文件的“骨架”整齐地显示,并带有缩进和所有内容。我在这里错过了什么?

【问题讨论】:

  • 基本上,引用你的变量。不要使用echo -e,因为它是非标准的。 printf 将在您添加引号时执行您想要的操作。
  • 为了完全确定,当我引用变量时,我必须双引号,例如 printf "$var1" ,对吧?
  • 双引号将评估里面的变量。单引号用于不会被评估的文字。
  • 好的,我想我明白了。我也在学习 Python,所以这整个“双引号/单引号”的东西有点混乱

标签: bash printf


【解决方案1】:

尝试echo -e 而不是printfprintf 用于打印格式化字符串。由于您没有使用引号保护 $head,因此 bash 将字符串拆分为命令。第一个单词(在第一个空格之前)形成格式字符串。其余的只是您未指定要打印的内容的参数。

echo -e "$head" > "$percorso"

-e 将您的 \n 评估为换行符。我将您的 &gt;&gt; 更改为 &gt;,因为您似乎希望这是整个文件,而不是附加到您可能拥有的任何现有文件中。

你必须小心 bash 中的引号。一件事情可以变成多件事情。这实际上使它更强大,但它可能会让人们学习感到困惑。请注意,我还将文件名 "$percorso" 也放在了双引号中。这会评估变量并确保它最终成为一件事。如果您使用单引号,它将是一个单词,但不会被评估。与 Python 不同的是,单引号和双引号之间有很大的区别。

如果你想像@chepner 指出的那样使用printf 来实现兼容性,请务必引用它:

printf "$head" > "$percorso"

其实这样更简单。

【讨论】:

  • 太棒了!它就像一个魅力。谢谢你的闪电回答,我会尽快接受你的回答,现在stackoverflow说我可以在6分钟内接受。
  • printfecho -e 更推荐,如果只是作为一个好习惯的话。 echo 的行为从一个 shell 到另一个 shell 差异很大,而 printf 的行为由 POSIX 明确定义。
  • @chepner 好点。我补充说。这种方式也更简单。我一开始就应该这样做。
  • 还有一点。由于printf 的第一个参数始终针对格式字符串进行处理,因此应避免使用内容未知的参数扩展。 (例如,考虑printf '%s'。)使用printf '%s' "$head" 是安全的。
  • creaHTML 有问题;它应该在值中嵌入实际的制表符和换行符,而不是需要特殊处理的有向图。
猜你喜欢
  • 1970-01-01
  • 2010-12-13
  • 2013-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 2015-04-16
  • 2011-12-28
相关资源
最近更新 更多