如何从stdin设置bash脚本的位置参数?

时间:2015-01-24 03:12:21

标签: bash

我有一个bash脚本,我希望从文件中读取它以获取它的参数集。基本上我的脚本在位置上读取参数($1$2$3等。)

while test $# -gt 0; do
  case $1 in
    -h | --help)
      echo "Help cruft"
      exit 0
      ;;
  esac
  shift
done

我希望其中一个选项可能是一个读取参数的配置文件(简单易用 config ),所以我希望set --命令可以正常工作({{1过度争论)。但是,由于它们是在文件中定义的,我必须将其读入并使用--来传递它们:

xargs

麻烦在于xargs在-c | --config) cat $2 | xargs set -- continue ;; 上骚扰,所以我不知道如何做到这一点。

注意:我意识到我可以使用--并设置变量;可能是最后的选择。我想知道我是否可以像上面那样做并简化文档

简化的示例脚本:

source config_file

1 个答案:

答案 0 :(得分:4)

xargs无法执行set,因为:

  1. set是内置的shell,而不是外部命令。 xargs只知道如何执行命令。 (一些具有相同名称的shell内置阴影命令,例如printftrue[。所以xargs可以执行这些命令,但语义可能不会与内置相同。)

  2. 即使xargs可以执行set,它也无效,因为xargs不会在shell的环境中运行; xargs执行的每个命令都是一个单独的过程。因此,如果您这样做,您将不会收到任何错误:

    echo a b c | xargs bash -c 'set -- "${@}"' _
    

    但它也不会做任何有用的事情。 (用set替换echo,你会发现它确实调用了命令。)


  3. 如何从文件中读取参数。

    首先,您需要回答这个问题:在文件中包含参数意味着什么?它们是单独的以空格分隔的单词,没有机制在任何参数中包含空格吗? (这也是xargs在默认模式下工作所必需的,所以这不是一个完全不合理的假设,尽管它几乎肯定会让你在某些时候遇到麻烦。)

    在这种情况下,您根本不需要xargs;你可以使用命令替换:

    set -- $(<file)
    

    虽然这样可以正常工作,但这不会:

    echo a b c | set -- $(</dev/stdin)
    

    因为管道(由 | 运算符创建)导致任一侧的进程在子shell中运行,因此set不会修改当前shell的环境变量。


    更强大的解决方案

    假设每个参数都在文件的一行中,这样就可以在参数中包含空格,但不能在换行符中包含空格。然后我们可以使用有用的mapfile内置函数将参数读入数组,并从数组中设置位置参数。 (或者直接使用数组,但这是一个不同的问题。)

    mapfile -t args < file
    set -- "${args[@]}"
    

    再次注意管道mapfile;它不起作用,原因与它不适用于set