【问题标题】:How to avoid unexpected newlines in quoted arguments如何避免引用参数中出现意外的换行符
【发布时间】:2023-03-06 04:15:01
【问题描述】:

在使用 bash 和多字参数时,也许有人可以向我解释以下意外结果?当我传递这样一个不带引号的echo 参数时,我得到:

> for i in *.jpg; do tmp=`basename -s .jpg $i`; echo $tmp; done       
25 Chaos auf Schloss Burgeck
26 Die kaiserliche Urkunde
[...]

但是当我添加引号时,我得到以下结果:

> for i in *.jpg; do tmp=`basename -s .jpg $i`; echo "$tmp"; done     
25
Chaos
auf
Schloss
Burgeck
26
Die
kaiserliche
Urkunde
[...]

发生了什么事?这两个输出都无法用于进一步处理,例如 mdkir

【问题讨论】:

  • 如果您的文件名称中有空格,那么正确的工具是 find,而不是 globbing。
  • 您看到不同输出的原因是因为使用引号,特殊字符如 \n \t 等受到尊重。
  • @MatiasBarrios 我不敢苟同。处理带有空格的路径,尤其是 find 返回的换行符比使用通配符要困难得多。 find 也较慢。

标签: bash variables spaces


【解决方案1】:

经验法则:总是引用你的变量,除非你知道你在做什么。

在您的第二个命令中,您只引用了一个变量。 $i 仍然没有被引用,因此受到 bash 的分词。因此,在第一次迭代中,basename 命令没有接收到一个参数25 Chaos auf Schloss Burgeck.jpg,而是接收到五个参数25ChaosaufSchlossBurgeck.jpg。对于每个参数,basename 打印一行。

在您的命令的完全未引用的变体中,这没有问题,因为在$tmp 的分词期间,bash 删除了换行符。 echo 然后插入空格,以便(偶然)最终结果再次正确。但是,如果您的文件名包含多个后续空格或特殊符号(如 *),则结果也会在未加引号的变体中关闭。

脚本的更正版本:

for i in *.jpg; do tmp=$(basename -s .jpg "$i"); echo "$tmp"; done

相当于

for i in *.jpg; do echo "${i%.jpg}"; done

【讨论】:

    猜你喜欢
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 2019-07-09
    相关资源
    最近更新 更多