如何在bash中间接地分配一个variables来从Standard In,File和执行输出中获取多行数据

我在这里和其他地方发现了许多片段,回答了这个问题的一部分。 我甚至设法以低效的方式在很多步骤中做到这一点。 如果可能的话, 我真的很想find执行这个任务的单行执行 ,而不是分配给一个variables,并复制它几次来执行任务。

例如

executeToVar () { # Takes Arg1: NAME OF VARIABLE TO STORE IN # All Remaining Arguments Are Executed local STORE_INvar="${1}" ; shift eval ${STORE_INvar}=\""$( "$@" 2>&1 )"\" } 

总的来说,如果$ executeToVar SOME_VAR ls -l * #实际上会填充SOME_VAR和从其余参数中取出的ls -l *命令执行的输出。 但是,如果命令在最后输出空行,(对于例如- echo -e -n '\n\n123\n456\n789\n\n'应该在开始和结束处具有2个新行)这些被bash的子执行过程所剥夺。 我在其他类似的post中看到,通过在stream的末尾添加一个标记“x”来解决这个问题,例如将子执行转化为如下forms:

 eval ${STORE_INvar}=\""$( "$@" 2>&1 ; echo -nx )"\" # <-- ( Add echo -nx ) # and then if it wasn't an indirect reference to a var: STORE_INvar=${STORE_INvar%x} # However no matter how much I play with: eval "${STORE_INvar}"=\""${STORE_INvar%x}"\" # I am unable to indirectly remove the x from the end. 

无论如何,我还需要2个其他的变种,其中一个将STDIN stream分配给var,另一个将文件内容分配给var,我假设这个变种是$( cat ${1} ) ,或者可能$( cat ${1:--} )给我一个' – '如果没有文件名。 但是,除非我能够理清为确保多行variables的准确分配所需的x的移除,否则这些都不会起作用。

我也尝试过(但无济于事):

 IFS='' read -d '' "${STORE_INvar}" <<<"$( $@ ; echo -nx )" eval \"'${STORE_INvar}=${!STORE_INvar%x}'\" 

Solutions Collecting From Web of "如何在bash中间接地分配一个variables来从Standard In,File和执行输出中获取多行数据"

这接近于最佳 – 但放弃eval

 executeToVar() { local varName=$1; shift; printf -v "$1" %s "$("$@")"; } 

这个表达式仍然存在的一个问题是$()去掉了换行符。 如果你想防止这种情况发生,你需要在子shell中添加你自己的尾随字符,然后把它从你自己的地方剥离下来。

 executeToVar() { local varName=$1; shift; local val="$(printf %sx; "$@"; printf %sx)"; val=${val#x} printf -v "$varName" %s "${val%x}" } 

如果你想从标准输入读取所有内容到一个变量,这是特别容易的:

 # This requires bash 4.1 for automatic fd allocation readToVar() { if [[ $2 && $2 != "-" ]]; then exec {read_in_fd}<"$2" # copy from named file else exec {read_in_fd}<&0 # copy from stdin fi IFS= read -r -d '' "$1" <&$read_in_fd # read from the FD exec {read_in_fd}<&- # close that FD } 

用作:

 readToVar var < <( : "run something here to read its output byte-for-byte" ) 

…要么…

 readToVar var filename 

测试这些:

 bash3-3.2$ executeToVar var printf '\n\n123\n456\n789\n\n' bash3-3.2$ declare -p var declare -- var=" 123 456 789 " 

…和…

 bash4-4.3$ readToVar var2 < <(printf '\n\n123\n456\n789\n\n') bash4-4.3$ declare -p var2 declare -- var2=" 123 456 789 " 

在一个文件中存储什么错误:

  $ stuffToFile filename $(stuff) 

在“stuffToFile”测试一个。 > 1个参数,b。 在管道上输入

  $ ... commands ... | stuffToFile filename 

  $ stuffToFile filename < another_file 

“stoffToFile”是一个函数:

 function stuffToFile { [[ -f $1 ]] || { echo $1 is not a file; return 1; } [[ $# -lt 2 ]] && { cat - > $1; return; } echo "$*" > $1 } 

所以,如果“东西”有前后空行,那么你必须:

  $ stuff | stuffToFile filename