我正试图解决一些问题,其行为如下让我们引用一下情况在目录中,我有一些包含一些内容的脚本(不管它在做什么(
- 示例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实现的来源将是一个灵感。然后建立一个文件数据库->函数+正文,并列出具有相同函数+正文的所有文件。
对于足够简单的函数,awk
、perl
或python
脚本足以覆盖大多数情况。但最好的是完整的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.sh
和file2.sh
中存在相同的函数foo1
,在file3.sh
和file4.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