如何从保持位置参数的管道中读取?

如何从保持位置参数的管道中读取?

我正在编写一个小脚本,我想让它通过管道输入或命令行参数运行。

my_function() {
  for i in "$@"; do
    echo "$i"
    echo -----
  done
}

if [ -t 0 ]; then
  my_function "$@"    # command-line arguments
else
  my_function $(cat)  # pipe
fi

这些选项有效:

$ my_script 1 2 3 4
$ echo 1 2 3 4 | my_script
1
-----
2
-----
3
-----
4
-----

这也可以正常工作:

$ my_script 1 "2 3" 4
1
-----
2 3
-----
4
-----

当我试图保留管道中的位置参数时,问题就出现了:

$ echo 1 "2 3" 4 | my_script
1
-----
2
-----
3
-----
4
-----

$ echo 1 "'2 3'" 4 | my_script
1
-----
'2
-----
3'
-----
4
-----

相反my_function $(cat),我尝试使用read但没有好的结果,例如:

read input
my_function $input

对此有什么想法吗?我知道分词很难。

答案1

使用 bash 4.4 来看看这个技术:

function myf { 
  if ! [ -t 0 ];then 
    declare -a args=\($(</dev/stdin)\);
    set -- "${args[@]}"; 
  fi;
  for i in "$@";do 
    echo "$i";
    echo -----;
  done 
}

测试:

$ function myf { if ! [ -t 0 ];then declare -a args=\($(</dev/stdin)\);set -- "${args[@]}"; fi;for i in "$@";do echo "$i";echo -----;done }
$ myf 1 "2 3" 4
1
-----
2 3
-----
4
-----

$ echo $'1 "2 3" 4'|myf
1
-----
2 3
-----
4
-----

使用以下方法也可以获得相同的结果:

$ echo 1 \"2 3\" 4 |myf
$ echo 1 "'2 3'" 4 |myf

echo 1 "2 3" 4不会起作用,因为在这种语法中 bash 会忽略双引号:

$ echo 1 "2 3" 4
1 2 3 4

相关内容