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

时间:2016-08-03 10:30:56

标签: linux bash shell scripting command

我已经搜索过这个特殊问题,但是找不到任何有用的东西。

假设我在~/.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)"'

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

5 个答案:

答案 0 :(得分:3)

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

$ 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)。对于每个函数,它遍历该函数的代码(从类型的输出中跳过无用的行)并执行它们。所以最后它与拥有此代码相同......

echo "foo"
echo "bar"

...这正是函数内部的代码行,并且您是一个接一个地执行它们。

请注意,您还可以构建一个字符串变量,其中包含由; 分隔的所有代码行,而不是在每行上运行 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

答案 1 :(得分:2)

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

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

注意:

  • 与原始版本的不同之处在于它不再干扰标准输入。

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

答案 2 :(得分:1)

子进程看不到Shell函数,除非它们已导出。也许这是缺失的成分。

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

答案 3 :(得分:0)

这应该有效:

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

答案 4 :(得分:0)

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

foo() { echo bar ; }

现在有一个bash函数可以在一个(或多个)函数中打印。由于函数的内容用4个空格缩进,sed删除没有4个前导空格的任何行,然后删除前导空格,并在末尾添加';'每个功能:

# Usage: in_func <function_name1> [ ...<function_name2> ... ]
in_func() 
    { while [ "$1" ] ; do \
          type $1 | 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 三次,然后运行它:

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

输出:

bar
bar
bar