我如何间接在bash变量赋值从两个标准中,一个文件需要多行数据,和执行的输出 [英] How do I indirectly assign a variable in bash to take multi-line data from both Standard In, a File, and the output of execution

查看:358
本文介绍了我如何间接在bash变量赋值从两个标准中,一个文件需要多行数据,和执行的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

例如

  executeToVar()
{
    #注意到的Arg1:以存储变量名
    #所有剩余的参数被执行
    当地STORE_INvar =$ {1};转移
    的eval $ {STORE_INvar} = \\$($ @2 - ;&放大器; 1)\\
}

总体不工作,即 $ executeToVar SOME_VAR的ls -l *#将真正填补 SOME_VAR 与输出在执行的ls -l * 命令是从参数的其余采取。但是,如果命令是为了输出空行末,(对于如 - 回声-e -n的'\\ n \\ N123 \\ n456 \\ n789 \\ n \\ n 里面应该有在开始2个新的生产线和年底),这些是由庆典的副执行过程中剥离。我已经在类似于该其他职位看出,这已经通过将令牌的x到流,例如结束解决打开子执行到是这样的:

 的eval $ {STORE_INvar} = \\$($ @2>&放大器; 1;回声-nx)\\#<  - (添加回声-nx )
#,然后,如果它不是一个间接引用一个变种:
STORE_INvar = $ {STORE_INvar%X}
#但是无论我多么玩:
的eval$ {STORE_INvar}= \\$ {STORE_INvar%×}\\
#我无法间接地从末尾移除的X.

反正,我还需要在这2个其他的变种,一个分配 STDIN流来var和一个文件的内容分配给VAR哪些我认为将是涉及 $的变化(猫$ {1}),或者 $(猫$ {1: - })来给我一个' - '如果没有文件名。但是,没有将工作,​​直到我能理清去除,以保证多行变量的准确分配时所需要的x的。

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

  IFS =''读-d''$ {} STORE_INvar<<<$($ @;回声-n X)
EVAL \\'$ {} STORE_INvar = $ {!STORE_INvar%X}'\\


解决方案

这是接近最优的 - 但降评估

  executeToVar(){本地的varName = $ 1;转移; printf的-v$ 1%S$($ @); }

在一个问题这个提法仍是尾随换行符的 $()带。如果你想为$,你需要添加自己的尾随字符子shell里面,剥离其关闭自己p $ pvent。

  executeToVar(){
  当地的varName = $ 1;转移;
  当地VAL =$(的printf%S X;$ @;的printf%S X); VAL = $ {VAL#X}
  printf的-v$ varname的%S$ {VAL%X}
}


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

 #这需要自动分配的fd 4.1的bash
readToVar(){
  如果[[$ 2及和放大器; $ 2 = - ]!;然后
    EXEC {read_in_fd}<$ 2#从指定的文件复制
  其他
    EXEC {read_in_fd}<&安培; 0#从标准输入复制
  科幻
  IFS =读-r -d''$ 1<&安培; $#read_in_fd从FD读
  EXEC {read_in_fd}<&安培; - #接近,FD
}

...作为:

  readToVar VAR< ≤(:跑的东西在这里读它的输出字节为字节)

......或者......

  readToVar变种文件名


测试这些:

  bash3-3.2 $ executeToVar VAR的printf的'\\ n \\ N123 \\ n456 \\ n789 \\ n \\ n'
bash3-3.2 $申报-p VAR
声明 - VAR =123
456
789

......然后......

  bash4-4.3 $ readToVar VAR2< ≤(的printf的'\\ n \\ N123 \\ n456 \\ n789 \\ n \\ n)
bash4-4.3 $申报-p VAR2
声明 - VAR2 =123
456
789

I have found many snippets here and in other places that answer parts of this question. I have even managed to do this in many steps in an inefficient manner. If it is possible, I would really like to find single lines of execution that will perform this task, rather than having to assign to a variable and copy it a few times to perform the task.

e.g.

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

Overall does work, i.e. $ executeToVar SOME_VAR ls -l * # will actually fill SOME_VAR with the output of the execution of the ls -l * command that is taken from the rest of the arguments. However, if the command was to output empty lines at the end, (for e.g. - echo -e -n '\n\n123\n456\n789\n\n' which should have 2 x new lines at the start and the end ) these are stripped by bash's sub-execution process. I have seen in other posts similar to this that this has been solved by adding a token 'x' to the end of the stream, e.g. turning the sub-execution into something like:

eval ${STORE_INvar}=\""$( "$@" 2>&1 ; echo -n x )"\" # <-- ( Add echo -n x )
# 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.

Anyway, I also need 2 x other variants on this, one that assigns the STDIN stream to the var and one that assigns the contents of a file to the var which I assume will be variations of this involving $( cat ${1} ), or maybe $( cat ${1:--} ) to give me a '-' if no filename. But, none of that will work until I can sort out the removal of the x that is needed to ensure accurate assignment of multi line variables.

I have also tried (but to no avail):

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

解决方案

This is close to optimal -- but drop the eval.

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

The one problem this formulation still has is that $() strips trailing newlines. If you want to prevent that, you need to add your own trailing character inside the subshell, and strip it off yourself.

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


If you want to read all content from stdin into a variable, this is particularly easy:

# 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
}

...used as:

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

...or...

readToVar var filename


Testing these:

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

123
456
789

"

...and...

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

123
456
789

"

这篇关于我如何间接在bash变量赋值从两个标准中,一个文件需要多行数据,和执行的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆