将参数和标准输入读取到同一变量,保留空间

时间:2017-09-18 12:15:11

标签: bash shell

我试图编写一个程序来处理作为程序输入的文件,但我想支持值的管道输入以及通过参数发送它们。

例如,有人可能希望使用标志-dvs在当前目录中的所有文件上运行程序:

find . -type f | program -dvs

或者您可能想要这样做,但对于$ FILES_TO_CHECK变量中的所有文件:

echo "$FILES_TO_CHECK" | program -dvs

这是我到目前为止的代码:

tmp1() {
  local in=("$@")

  if read -t 0 -u 0; then
    local pipe=""
    read -d '' -u 0 pipe
    in+=(${pipe})
  fi

  local param
  for param in "${!in[@]}"; do
    echo "'$param' => '${in[$param]}'"
  done
}

测试:

echo "cba" "bca" "cba abc" | tmp1 "a" "b" "c" "abc" "abc cba"
echo; echo; echo
find . -type f
find . -type f | tmp1 "a" "b" "c" "abc" "abc cba"

以上给出了以下输出:

'0' => 'a'
'1' => 'b'
'2' => 'c'
'3' => 'abc'
'4' => 'abc cba'
'5' => 'cba'
'6' => 'bca'
'7' => 'cba'
'8' => 'abc'



./1
./2
./3
'0' => 'a'
'1' => 'b'
'2' => 'c'
'3' => 'abc'
'4' => 'abc cba'

哪个很接近,但不完全是我想要的:

'0' => 'a'
'1' => 'b'
'2' => 'c'
'3' => 'abc'
'4' => 'abc cba'
'5' => 'cba'
'6' => 'bca'
'7' => 'cba abc'



./1
./2
./3
'0' => 'a'
'1' => 'b'
'2' => 'c'
'3' => 'abc'
'4' => 'abc cba'
'5' => './1'
'6' => './2'
'7' => './3'

我不确定顶级情况(保持空间字符来自管道值)是可能的,但如果是,你会怎么做呢?
至于第二种情况,为什么find的输出不会被程序读取?

编辑:如果还有其他更好的方法,我也会听到所有的耳朵。 之后的实际循环要复杂得多,所以我想避免为参数设置一个循环,而为管道值设置另一个循环。

1 个答案:

答案 0 :(得分:1)

您的append = TRUE正在从标准输入读取空分隔的记录,但您的测试是发送空格分隔的字符串。用

进行测试
tmp

(这假定printf '%s\0' "cba" "bca" "cba abc" | tmp1 "a" "b" "c" "abc" "abc cba" find . -type f -print0 | tmp1 ... 的版本可以输出以null结尾的文件名。)

find内,您需要循环输入以获取每个文件,然后在将其添加到数组时引用tmp

$pipe

如果您使用的是if read -t 0 -u 0; then local pipe="" while read -d '' pipe; do in+=("$pipe") done fi 4.4或更高版本,则可以使用bash代替循环。

readarray