shell 递归调用实例

sample.txt表示一张图的关系:A -> {B;C}表示为从A结点到B和C结点都有一条路径,B或C如果没有出现在"->"的左边,表示B或C为终结点,图中没有环。这也可以表示为一个程序中的函数调用关系,图中没有环说明函数调用过程中没有对某函数的直接递归或间接递归调用。写一个shell脚本程序,找出以某函数为起始结点的调用图。

sample.txt

1 -> {0};

2 -> {0};
3 -> {2;1};
5 -> {4;3;2};
7 -> {3;2;6};
8 -> {7;6;5;4;3};

9 -> {8;7;6};

------------------------------------

程序思想:

1.将“->"左侧的标号保存在globalseqnums变量中

2.先根据输入的结点号找到其在sample.txt 的对应行,并保存在变量line中;

3.将line中箭头右侧部分截取出来,保存在变量arrowright中;

4.将‘{’和‘}’去掉,并将各标号用空格隔开,以单词形式识别

5.对4中每一个单词标号进行查找,如果在globalseqnums中有匹配,则说明其是中间节点;如果没有匹配,则说明是终结点

6.在5中如果是中间结点,则先将标号保存在savedseqnum变量中,然后递归调用,重复2到4过程;如果是终结点,返回到上一层递归调用


get_call_graph.sh

#!/bin/bash

filename=
globalseqnums=
savedseqnum=
space=" "

function find_spec_line()
{
if [ $# -ne 1 ]
then 
echo "usage:  find_spec_line  <num>"
exit 1
fi
local submark=$1
local string=`sed -n '/^'$submark' /p' $filename`


echo $string
}

function get_arrowright()
{
if [ $# -ne 1 ]
then 
echo "usage:  get_arrowright  <string>"
exit 1
fi
local string=$1
local arrowright=`echo $string|awk -F " -> " '{print $2}'`

echo $arrowright
}

function strip_arrowright()
{
if [ $# -ne 1 ]
then 
echo "usage:  strip_arrowright  <string>"
exit 1
fi

local str=$1
local striped=`echo $str|sed 's/{//g'|sed 's/};//g'`
striped=`echo $striped|awk -F ";" '{for(i=1;i<=NF;i++)print $i}'`

echo $striped
}

function search()
{
local word
local line
local arrowright
local striped_arrowright

if [ $# -ne 1 ]
then 
echo "usage:  search  <string>"
exit 1
fi

word=$1
echo $savedseqnum|grep -w $word 2>&1 > /dev/null
if [ $? -ne 0 ]
then
savedseqnum=$savedseqnum$word$space
fi

line=`find_spec_line "$word"`  
arrowright=`get_arrowright "$line"`
striped_arrowright=`strip_arrowright "$arrowright"`

for word in $striped_arrowright
do
echo $globalseqnums|grep -w $word 2>&1 > /dev/null
if [ $? -eq 0 ]
then
echo $savedseqnum|grep -w $word 2>&1 > /dev/null
if [ $? -ne 0 ]
then
savedseqnum=$savedseqnum$word$space
fi
search "$word"
else
return
fi
done
}

function display_call()
{
local line
local start=0
if [ $# -ne 1 ]
then 
echo "usage:  display_call  <string>"
exit 1
fi


seqnums=$1
for num in $seqnums
do
line=`sed -n '/^'$num' ->/p' $filename`
if [ -n "$line" ]
then
if [ $start -eq 0 ]
then
start=1
echo $line > newsample.txt
else
echo $line >> newsample.txt
fi
fi
done
}

filename=sam1
globalseqnums=`awk -F " -> " '{print $1}' $filename`
num_to_print=$1

search "$num_to_print"

echo $savedseqnum
display_call "$savedseqnum"
cat newsample.txt

----------------------------------------------------------------------------------

root# get_call_graph.sh 9

9 8 7 3 2 1
9 -> {8;7;6};
8 -> {7;6;5;4;3};
7 -> {3;2;6};
3 -> {2;1};
2 -> {0};
1 -> {0};

root# get_call_graph.sh 5

5 4 2 3 1
5 -> {4;3;2};
4 -> {2;0};
2 -> {0};
3 -> {2;1};
1 -> {0};


程序能够实现要求,就是效率有些低,刚开始学习shell编程,还没有想到其他好算法。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值