【问题标题】:sed fails when "shopt -s nullglob" is set设置“shopt -s nullglob”时 sed 失败
【发布时间】:2015-03-19 19:37:25
【问题描述】:

几天前,我开始编写一个小 bash 脚本,它应该总结文件夹中所有 PDF 的页数和文件大小。它现在工作得很好,但还有一件事我不明白。

如果设置了shopt -s nullglob,为什么 sed 总是失败?有人知道为什么会这样吗?

我在 Ubuntu 14.04 中使用 GNU Bash 4.3 和 sed 4.2.2。

set -u
set -e

folder=$1

overallfilesize=0
overallpages=0
numberoffiles=0

#If glob fails nothing should be returned
shopt -s nullglob

for file in $folder/*.pdf
do

  # Disable empty string if glob fails
  # (Necessary because otherwise sed fails ?:|)
  #shopt -u nullglob

  # This command is allowed to fail
  set +e
  pdfinfo="$(pdfinfo "$file" 2> /dev/null)"
  ret=$? 
  set -e  

  if [[ $ret -eq 0 ]]
  then 
    #Remove every non digit in the result
    sedstring='s/[^0-9]//g'
    filesize=$(echo -e "$pdfinfo" | grep -m 1 "File size:" | sed $sedstring)
    pages=$(echo -e "$pdfinfo" | grep -m 1 "Pages:" | sed $sedstring)

    overallfilesize=$(($overallfilesize + $filesize))  
    overallpages=$(($overallpages+$pages))  
    numberoffiles=$(($numberoffiles+1))  
  fi

done

echo -e "Processed files: $numberoffiles"
echo -e "Pagesum: $overallpages"
echo -e "Filesizesum [Bytes]: $overallfilesize"

【问题讨论】:

    标签: bash sed glob shopt


    【解决方案1】:

    这里有一个更简单的重现问题的测试用例:

    #!/bin/bash
    shopt -s nullglob
    pattern='s/[^0-9]//g'
    sed $pattern <<< foo42
    

    预期输出:

    42
    

    实际输出:

    Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...
    (sed usage follows)
    

    发生这种情况是因为 s/[^0-9]//g 是一个有效的 glob(匹配像 s/c/g 这样的 dir 结构),并且您要求 bash 解释它。由于您没有匹配的文件,nullglob 会启动并完全删除该模式。

    双引号可防止分词和全局解释,这几乎总是您想要的:

    #!/bin/bash
    shopt -s nullglob
    pattern='s/[^0-9]//g'
    sed "$pattern" <<< foo42
    

    这会产生预期的输出。

    您应该始终对所有变量引用进行双引号,除非您有特定的理由不这样做。

    【讨论】:

    • 这同样适用于failglob shopt。你的测试用例也适合这个。
    猜你喜欢
    • 2019-06-24
    • 1970-01-01
    • 2011-09-20
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    相关资源
    最近更新 更多