Bash:在具有相同内容的文件中查找函数



我正试图解决一些问题,其行为如下让我们引用一下情况在目录中,我有一些包含一些内容的脚本(不管它在做什么(

  • 示例1.sh
  • example2.sh
  • example3.sh
  • 。。。等等

总共有50个脚本其中一些脚本包含相同的功能,例如

function foo1
{
echo "Hello"
}

在一些脚本中,函数可以命名为相同的,但有其他内容或修改,例如

function foo1
{
echo "$PWD"
}

function foo1
{
echo "Hello"
ls -la
}

我必须在这些脚本中找到具有相同名称和相同内容的相同函数例如foo1 example1.sh和example2.sh中相同或修改的内容->我想要什么foo1 example1.sh和example3.sh中的其他内容->不感兴趣

我的问题是,解决这个问题的最佳方法是什么?你觉得怎么样?我的想法是对所有脚本和重复函数的grep名称中的内容进行排序。我设法做到了,但这仍然不是我想要的,因为我必须用这个函数检查每个文件并检查其内容。。。这让人头疼,因为有些函数有10个脚本。。。

我想知道如何从重复函数中提取内容,但我不知道如何做到,你觉得呢?或者你还有其他建议?

提前感谢您的回答!

解决这个问题的最佳方法是什么?

编写一个shell语言标记器,并实现足够的语法解析,以便从文件中提取函数定义。shell实现的来源将是一个灵感。然后建立一个文件数据库->函数+正文,并列出具有相同函数+正文的所有文件。

对于足够简单的函数,awkperlpython脚本足以覆盖大多数情况。但最好的是完整的shell语言标记器。

不要使用function name {。而是使用name() {。请参阅bash过时和不推荐使用的语法。


使用以下文件:

# file1.sh
function foo1
{
echo "Hello"
}

# file2.sh
function foo1
{
echo "Hello"
}
# file3.sh
function foo1
{
echo "$PWD"
}

# file4.sh
function foo1
{
echo "$PWD"
}

以下脚本:

printf "%sn" *.sh |
while IFS= read -r file; do
sed -zE '
s/(function[[:space:]]+([[:print:]]+)[[:space:]]*{|(function[[:space:]]+)?([[:print:]]+)[[:space:]]*([[:space:]]*)[[:space:]]*{)([^}]*)}/x0124n5x02/g;
/x01/!d;
s/[^x01x02]*x01([^x01x02]*)x02[^x01x02]*/1nx00/g
' "$file" |
sed -z 's~^~'"$file"'x01~';
done |
awk -v RS='' -v FS='1' '
{cnt[$2]++; a[$2]=a[$2]" "$1}
END{ for (i in cnt) if (cnt[i] > 1) print a[i], i }
'

输出:

file1.sh file2.sh foo1
echo "Hello"

file3.sh file4.sh foo1
echo "$PWD"

表示在file1.shfile2.sh中存在相同的函数foo1,在file3.shfile4.sh中存在相同函数foo1

还要注意,脚本可以而且可以:

if condition; then
func() { echo something; }
else
func() { echo something else; }
fi

一个真正的代币化者也必须考虑到这一点。

创建每个函数内容的消息摘要,并将其用作关联数组中的键。添加包含相同函数摘要的文件以查找重复项。

您可能希望规范函数内容中的空间,并调整正则表达式地址范围。

#!/usr/bin/env bash
# the 1st argument is the function name
func_name="$1"
func_pattern="^function $func_name[[:blank:]]*$"
shift
declare -A dupe_groups
while read -r func_dgst file; do # collect results in an associative array
dupe_groups[$func_dgst]+="$file "
done < <( # the remaining arguments are scripts
for f in "${@}"; do
if grep --quiet "$func_pattern" "$f"; then
dgst=$( # use an address range in sed to print function contents
sed -n "/$func_pattern/,/^}/p" "$f" | 
# pipe to openssl to create a message digest
openssl dgst -sha1 )
echo "$dgst $f"
fi
done )
# print the results
for key in "${!dupe_groups[@]}"; do
echo "$key ${dupe_groups[$key]}"
done

我用您的示例{1..3}进行了测试。sh文件添加了以下示例4.sh以获得重复的函数。

示例4.sh

function foo1
{
echo "Hello"
ls -la
}
function another
{
echo "there"
}

运行

./group-func.sh foo1 example1.sh example2.sh example3.sh example4.sh

结果

155853f813e944a7fcc5ae73ee2d959e300d217示例1.sh7848af9bb9d48c5cb643f34b3e5ca26cb5bfbdd示例2.sh4771de27523a765bb0dbf070691eacbae841375示例3.sh示例4.sh

相关内容

  • 没有找到相关文章