省略传递空引用的参数

时间:2015-07-18 09:00:17

标签: bash arguments argument-passing variable-expansion

我在bash脚本中有一些变量,可能包含文件名或未设置。他们的内容应作为程序的附加参数传递。但是当变量未设置时,这会留下一个空参数。

$ afile=/dev/null
$ anotherfile=/dev/null
$ unset empty
$ cat "$afile" "$empty" "$anotherfile"
cat: : No such file or directory

没有引号,它可以正常工作,因为简单地省略了附加参数。但由于变量可能包含空格,因此必须在此引用它们。

我知道我可以简单地将整条线包裹在空虚的测试中。

if [ -z "$empty" ]; then
  cat "$afile" "$anotherfile"
else
  cat "$afile" "$empty" "$anotherfile"
fi

但是对每个变量进行一次测试会导致一个庞大而复杂的决策树。

对此有更紧凑的解决方案吗? bash可以省略引用的空变量吗?

4 个答案:

答案 0 :(得分:1)

尝试:

printf "%s\n%s\n%s\n" "$afile" "$empty" "$anotherfile" | egrep -v '^$' | tr '\n' '\0' | xargs -0 cat

答案 1 :(得分:1)

使用数组可以实现纯粹的bash解决方案。虽然"$empty"将评估为空参数,但"${empty[@]}"将扩展为引用的所有数组字段,在这种情况下,这些字段均为无。

$ afile=(/dev/null)
$ unset empty
$ alsoempty=()
$ cat "${afile[@]}" "${empty[@]}" "${alsoempty[@]}"

在无法选择阵列的情况下,请参阅pasaba por aqui的更多通用答案。

答案 2 :(得分:1)

对于像cat这样的命令,你可以用空文件替换空参数,你可以使用标准的shell默认替换语法:

cat "${file1:-/dev/null}" "${file2:-/dev/null}" "${file3:-/dev/null}"

或者,您可以通过管道(如下所示)或通过进程替换从存在的参数创建连接的输出流:

{ [[ -n "$file1" ]] && cat "$file1";
  [[ -n "$file2" ]] && cat "$file2";
  [[ -n "$file3" ]] && cat "$file3"; } | awk ...

这可以通过效用函数简化:

cat_if_named() { [[ -n "$1" ]] && cat "$1"; }

cat建立新文件的特定情况下,您可以执行一系列追加:

# Start by emptying or creating the output file.
. > output_file
cat_if_named "$file1" >> output_file 
cat_if_named "$file2" >> output_file 
cat_if_named "$file3" >> output_file 

如果你需要保留各个参数 - 例如,如果你想将列表传递给grep,它将打印文件名和匹配项 - 你可以建立一个参数数组,只选择存在的参数:

args=()
[[ -n "$file1" ]] && args+=("$file1")
[[ -n "$file2" ]] && args+=("$file2")
[[ -n "$file3" ]] && args+=("$file3")

使用bash 4.3或更高版本,您可以使用nameref创建实用程序功能来执行上述操作,这几乎可以肯定是解决问题的最紧凑和最通用的解决方案:

non_empty() {
  declare -n _args="$1"
  _args=()
  shift
  for arg; do [[ -n "$arg" ]] && _args+=("$arg"); done
}

例如:

non_empty my_args "$file1" "$file2" "$file3"
grep "$pattern" "${my_args[@]}"

答案 3 :(得分:1)

您可以使用alternate value parameter expansion${var+altvalue})来包含引用的变量IF:

cat ${afile+"$afile"} ${empty+"$empty"} ${anotherfile+"$anotherfile"}

由于双引号位于备用值字符串中(不在整个参数表达式中),因此只有在设置变量时它们才会生效。请注意,您可以使用+(如果设置了变量则使用备用值)或:+(如果变量设置为非空,则使用备用值)。