【问题标题】:How to write the content of a unknown shell variable to stdout in a safe way如何以安全的方式将未知 shell 变量的内容写入标准输出
【发布时间】:2018-12-22 08:21:22
【问题描述】:

到目前为止,我只知道我所读到的内容,而且我对如何按原样实际回显变量感到困惑。

  • 如果var='-n'echo "$var" 可能会失败
  • printf '%s\n' "$var" 可能会因为 shell 未实现而失败printf
  • echo -- "$var" 可能会失败,因为它是 gnu 扩展

所以如果我不得不猜测:

echo x"$var"|sed 's#^x##1' 将是唯一的方法,但我从未遇到过这种模式。为什么?


作为一个具体的问题:

for source; do
  target="$(echo "$source"|sed 's#[^a-z0-9]\+#.#')"
  # do stuff with $source and $target
done

如果我的脚本是由某个 my_script * cron 执行的,这是否可行,或者有人可以通过将名为“-n”的文件放在某处来“破解”/“破坏”我的脚本?

我如何写echo "$var" 使其不会中断?

【问题讨论】:

  • 你能举一个shell的例子,它不能用printf '%s\n' "$var"做正确的事情吗?如果 shell 没有实现 printf(例如在 OpenBSD 上使用 sh/ksh),将会使用一个外部实用程序。
  • 如果 shell 没有实现 printf,它就不是 POSIX shell。使用printf
  • printf 实际上比echo 更便携(就其行为的标准强制保证而言)。请参阅pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html 的应用程序使用和基本原理部分;引用前者的话:除非-n(作为第一个参数)和转义序列都被省略,否则不可能在所有 POSIX 系统中使用可移植的 echo。
  • 另一个注意事项:这是即使shellcheck -ssh 也无法理解的基本内容之一。这可能是因为如果 shellcheck 会警告任何使用没有固定值的 echo 是不合理的。

标签: shell echo


【解决方案1】:

这行得通吗,或者有人可以通过放置来“破解”/“破坏”我的脚本 在某处有一个名为“-n”的文件?

没有错:

target="$(echo "$source"|sed 's#[^a-z0-9]\+#.#')"

发生了什么:

  • "$(...)" 是一个命令替换,它将替换命令的结果作为值——在这种情况下,结果被分配给target
  • echo "$source"|sed 's#[^a-z0-9]\+#.#' 简单地将echo 的输出(例如source 中的内容)传递给sed,以便将每个字符(不是小写字母或数字后跟+)简单替换为期间 1。注意:$source 周围的引号 ".." 在命令替换中是正确的。
  • 没有内在的原因将-n 分配给变量会导致任何恶作剧。你对变量做了什么是另一个问题,但只要说很难看到任何问题就足够了。
  • “POSIX-shell 没有实现printf”——嗯?任何没有实现printf 的shell 将更像是一个例外而不是规则。请参阅printf - The Open Group Library,即 POSIX。

如果您尝试以'-' 开头的printf 输出,只需在输出前面加上"--" 以在您要打印的字符串之前指示End-of-Options去好。以"-n" 为例,printf 是您输出以单个'-' 开头的变量的唯一方法,例如:

$ t="-n"

$ printf -- "%s\n" "$t"
-n

(注意:您不必在printf "%s\n" "$var" 中包含"--",您必须将其包含在printf -- "-foo\n" 中的唯一情况是,否则您将收到"invalid option error"

对于echo,您可以使用-e 启用反斜杠转义解释,并包含一个退格,例如

$ echo -e " \b$t"
-n

我认为这涵盖了所有问题。如果没有,请告诉我。此外,如果您有任何其他问题,请在下方发表评论或编辑并添加到您的问题中。

脚注:

  1. 注意:+ 不是基本正则表达式的一部分,不需要转义,但如果有任何问题,包含在字符类中会更安全 自己的,例如[^a-z0-9][+]

【讨论】:

  • 为什么你认为var='-n'; echo "$var"var='-x'; echo "$var" 相比没有做一些意想不到的事情,你都试过了吗?
  • 因为echo 正在写入stdout,它正在输出$var。如果没有-e 和退格键,可能发生的最坏情况是-n 被解释为"do not output the trailing newline",在这种情况下-n 本身被echo 消耗。 (是的,我都试过了)。 echo -e " \b-n"echo -e " \n$var"。在处理'-'作为前导字符时,您需要检查第一个字符是否带有,例如高级 shell 中的参数扩展,或 POSIX 中的 expr substring "$var" 1 1
  • 注意:expr substring "$var" 1 1 应该是 expr substr "$var" 1 1(注意 substr 不是 substring
  • 没问题,这实际上是一个非常好的问题,它揭示了echoprintf 很少解决的问题。这只是echo 的不足之处。
  • printf '%s\n' 不需要-- 因为%s 不以- 开头。
猜你喜欢
  • 1970-01-01
  • 2014-07-18
  • 1970-01-01
  • 2012-07-22
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 2020-01-29
  • 2014-07-03
相关资源
最近更新 更多