2016-08-03 82 views
2

我已经搜索过有关此特定问题的信息,但找不到任何有用的信息。如何使用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

我想运行三个功能addCaf,在短短的一行addAospaddXos内的所有命令。

任何帮助表示赞赏。

我已经尝试过:

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)"' 

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

+0

不知道你在问什么,但如果你想在一行上创建一个函数,你可以使用'function f(){echo hi; }'。注意最后的';'。 –

+0

那么,我想在一个字符串中的一行中获取函数的**内容**。 – xdevs23

+0

为什么你需要这些功能的内容,而不是仅仅运行这些功能呢?因为你需要将参数中的调用嵌入'repo'(不管是什么)? '输入addXos'确实(大部分)你需要什么?或者实际上'声明-f addXos'? –

回答

0

做一个虚拟函数富(),这只是打印“酒吧”

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="`in_func foo`" ; echo $baz 

输出:

echo bar; 

运行什么在FOO()

eval "$baz" 

输出:

bar 

分配什么在FOO()$巴兹三次,并运行它:

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

输出:

bar 
bar 
bar 
+1

警告:有些人认为大多数语言的形式是'eval' ** ** ee ** _ ville_,不完全没有理由](http:// stackove rflow.com/questions/2571401/why-exactly-is-eval-evil?s=2|2.9495)。 – agc

+0

这工作。只需复制并粘贴'in_func'函数,然后运行以下命令:'repo forall -c“$(in_func addAosp)$(in_func addXos)$(in_func addCaf)''但是'repo'工具有点bug。那么,这个答案是正确的。 – xdevs23

+1

删除间距并添加';'-s对于较高的bash结构(例如'while','for','if')不起作用,例如:'boo(){while false ;做echo echo bar; done; echo ok;}; eval $(in_func boo)'给出一个语法错误(问题在于'in_func'在'do'后面加了一个';')。有限的这种方式,但唉这是被接受的。 –

0

这应该工作:

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

+0

我不想要功能的结果,我想要的内容。 – xdevs23

+0

好吧,我的坏,我误解了你的问题:( – Jawad

+0

没问题,但建议很好 – xdevs23

1

壳牌功能是不可见的子进程,除非他们出口。也许这是缺少的成分。

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

即使你的答案可能是正确的,我面临以下错误信息:'有错误,终止池:OSError:[Errno 2 ]没有这样的文件或目录,似乎与'repo'工具有关,无论如何,这并不能帮助我解决这个问题。你知道我如何回显一个函数的**内容**吗?单个命令? – xdevs23

2

您可以使用,然后分析其输出做任何你想要的代码行做的。

$ 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 
+0

这几乎是我所需要的,你能告诉我如何删除'foo是一个函数'和'foo(){}',只保留这些行在一行中,像这样:'echo foo; echo foo2; echo foo3; ...',假设那些命令是在那个特定的函数中的? – xdevs23

+0

现在看看 –

2

假设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" 

注:

  • 与原始版本的区别是,这不再是内部与标准输入兼容。

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

相关问题