如何使用 bash 获取字符串中函数的内容?

How to get the content of a function in a string using bash?

我已经搜索过这个特定问题,但找不到任何有用的信息。

假设我在 ~/.bashrc 中定义了以下函数(注意:这是伪代码!):

ANDROID_PLATFORM_ROOT="/home/simao/xos/src/"

function getPlatformPath() {
  echo "$ANDROID_PLATFORM_ROOT"
}

function addCaf() {
  # Me doing stuff
  echo "blah/$(getPlatformPath)"
}

function addAosp() {
  # Me doing stuff
  echo "aosp/$(getPlatformPath)"
}

function addXos() {
  # Me doing stuff
  echo "xos/$(getPlatformPath)"
}

function addAllAll() {
  cd $(gettop)
  # repo forall -c "addCaf; addAosp; addXos" # Does not work!
  repo forall -c # Here is where I need all those commands
}

我的问题:

我需要在一行中获取函数 addCafaddAospaddXos

你可以 运行 跟随 bash(伪代码):

dothis; dothat; doanotherthing; trythis && succeedsdothis || nosuccessdothis; blah

我想 运行 三个函数 addCafaddAospaddXos 中的所有命令仅在一行中 .

感谢任何帮助。

我已经尝试过的:

repo forall -c "bash -c \"source ~/.bashrc; addAllAll\""

但效果不佳。

编辑:

澄清我的意思。

结果我想要这样的东西:

repo forall -c 'function getPlatformPath() { echo "$ANDROID_PLATFORM_ROOT"; }; ANDROID_PLATFORM_ROOT="/home/simao/xos/src/"; echo "blah/$(getPlatformPath)"; echo "aosp/$(getPlatformPath)"; echo "xos/$(getPlatformPath)"'

但我不想手动编写。相反,我想从已经存在的函数中获取这些行。

这应该有效:

repo forall -c "$(addCaf) $(addAosp) $(addXos)"

Shell 函数对子进程不可见,除非它们被导出。也许这就是缺少的成分。

export -f addCaf addAosp addXos
repo forall -c "addCaf; addAosp; addXos"

您可以使用 type 然后解析其输出以对代码行执行任何您想执行的操作。

$ foo() {
> echo foo
> }

$ type foo
foo is a function
foo () 
{ 
    echo foo
}

也许这个例子更清楚:

#!/bin/bash

foo() {
    echo "foo"
}

bar() {
    echo "bar"
}

export IFS=$'\n'

for f in foo bar; do
    for i in $(type $f | head -n-1 | tail -n+4); do
        eval $i
    done
done

exit 0

这是它的样子:

$ ./funcs.sh 
foo
bar

脚本所做的是首先循环遍历您拥有的所有函数(在本例中只有 foo 和 bar)。对于每个函数,它循环遍历该函数的代码(跳过 type 输出中无用的行)并执行它们。所以最后它和这个代码一样...

echo "foo"
echo "bar"

...这就是函数内部的代码行,你正在一个接一个地执行它们。

请注意,您还可以构建一个字符串变量,其中包含由 ; 分隔的所有代码行 if 而不是 运行 eval 在每一行你做这样的事情:

code_lines=

for f in foo bar; do
        for i in $(type $f | head -n-1 | tail -n+4); do
                if [ -z $code_lines ]; then
                        code_lines="$i"
                else
                        code_lines="${code_lines}; $i"
                fi  
        done
done

eval $code_lines

假设 repo forall -c 将下一个位置参数解释为 bash -c,尝试:

foo () { 
    echo "foo!"
}
boo () { 
    if true; then
        echo "boo!"
    fi
}
echo works | bash -c "source "<(typeset -f foo boo)"; foo; boo; cat"

注:

  • 与原版不同的是不再干扰stdin

  • <(...) 替换是未转义的,因为它 必须 由原始 shell 执行,其中 fooboo 首先被定义。它的输出将是一个 /dev/fd/63 形式的字符串,它是一个传递给第二个 shell 的文件描述符,其中包含转发的定义。

创建一个虚拟函数 foo(),它只打印 "bar":

foo() { echo bar ; }

现在有一个 bash 函数来打印 一个(或多个)函数中的内容。由于函数的内容缩进了 4 个空格,sed 删除了没有 4 个前导空格的任何行,然后也删除了前导空格,并添加了一个 ';'每个函数结束:

# Usage: in_func <function_name1> [ ...<function_name2> ... ]
in_func() 
    { while [ "" ] ; do \
          type  | sed  -n '/^    /{s/^    //p}' | sed '$s/.*/&;/' ; shift ; \
      done ; }

打印 foo():

中的内容
in_func foo

输出:

echo bar;

foo()中的内容分配给字符串$baz,然后打印$baz:

baz="`in_func foo`" ; echo $baz

输出:

echo bar;

运行 foo():

里有什么
eval "$baz"

输出:

bar

foo() 中的内容分配给 $baz 三次,然后 运行 it:

baz="`in_func foo foo foo`" ; eval "$baz"

输出:

bar
bar
bar