在 python 中提取 java 主要 class 名称
Extracting java main class name in python
我在 python 脚本中有字符串,其中包含一些 java
代码。
我如何从中提取基础 java class 名称以便使用 subprocess
?
执行它
我认为它可以使用正则表达式来实现,但我不知道如何实现。
样本:
a = """
import java.util.Scanner;
class sample{}
class second
{
static boolean check_prime(int a)
{
int c=0;
for (int i=1;i<=a; i++) {
if(a%i==0)
c++;
}
if(c == 2)
return true;
else
return false;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Enter two numbers");
int a = in.nextInt();
int b = in.nextInt();
if(check_prime(a) && check_prime(b))
{
if(b-a==2 || a-b==2)
System.out.println("They are twin primes");
else
System.out.println("They are not twin primes");
}
else
System.out.println("They might not be prime numbers");
}
}
"""
这是一个粗略的方法:
import re
b = a.split()
str = b[b.index("class")+1]
javaclass = re.sub("{.*$","",str)
print (javaclass)
...本质上是获取所有单词,并找到第一次出现 "class" 之后的第一个单词。如果您遇到类似
的情况,它还会删除“{”及其后的任何内容
class MyClass{
但是,如果一个文件中有多个 类,则需要做更多的工作。
A main class is a class which contains the public static void main function.
如果在您的环境中可行;您可以使用可以解析 Java 源代码的库,例如 plyj
or javalang
:
#!/usr/bin/env python
import javalang # $ pip install javalang
tree = javalang.parse.parse(java_source)
name = next(klass.name for klass in tree.types
if isinstance(klass, javalang.tree.ClassDeclaration)
for m in klass.methods
if m.name == 'main' and m.modifiers.issuperset({'public', 'static'}))
# -> 'second'
如果在 Java 源的顶部有一个包声明,例如 package your_package;
即,如果完整的 class 名称是 your_package.second
那么你可以得到包名称为 tree.package.name
.
或者您可以使用解析器生成器,例如 grako
并指定一个 Java 语法子集,它足以在您的案例中获得 class 名称。如果输入是高度规则的;如果您对代码结构的假设是错误的,您可以尝试使用正则表达式并预计它会失败。
正如我在评论中所说,使用 re.findall()
像这样:
re.findall('class (\w*)', a)
作为函数名,findall()
可以找到所有的class个名字。并在此处使用 \w
将匹配所有 ascii 字母(如果您使用 class MyClass{
,将比 .*
更好)。
关于找到主要 class,使用 re.S
像这样:
for i in re.split('\nclass ', a)[1:]: # will match the main code block and the class name of all classes
if re.search('\n\s*public static void main', i): # check if 'public static void main' in a class
print(re.search('(\w*)', i).group(1)) # and print out the class name
一种更简单的方法,只有一行使用列表理解:
[re.search('(\w*)', i).group(1) for i in re.split('\nclass ', a) if re.search('\n\s*public static void main', i)]
正如您猜想的那样,使用正则表达式可以近似解决问题。但是,请记住一些技巧:
- class 名称不能以空格结尾,因为
MyClass{
是合法且常见的
- 可以在class名称后提供类型参数,例如
MyClass<T>
,编译后的.class
文件名不受此类型参数影响
- 一个文件可以有多个顶层 class,但是不能声明一个 public 而这个 class 不能 与文件同名
- 与文件同名的publicclass可能有内部class(甚至可能是public)但是这些必须在外部 class 声明。
这些提示导致搜索短语 public class
的第一次出现,捕获下一个 运行 个字符,然后寻找空格、{
或 <
字符.
这是我想出来的(可能有点难看):public\s*(?:abstract?)?\s*(?:static?)?\s*(?:final?)?\s*(?:strictfp?)?\s*class\s*(\w.*)\s*,?<.*$
仅使用正则表达式几乎是行不通的。作为为什么它不能的一个基本例子,考虑这个:
public class A {
public static void ImDoingThisToMessYouUp () {
String s = "public static void main (String[] args) {}";
}
}
public class B {
public static void main (String[] args) {}
}
你明白了......Regex 总是会被愚弄,以为他们找到了一些你正在寻找的东西。您必须依赖更高级的库进行解析。
我会选择 J.F。塞巴斯蒂安的回答。
我在 python 脚本中有字符串,其中包含一些 java
代码。
我如何从中提取基础 java class 名称以便使用 subprocess
?
执行它
我认为它可以使用正则表达式来实现,但我不知道如何实现。
样本:
a = """
import java.util.Scanner;
class sample{}
class second
{
static boolean check_prime(int a)
{
int c=0;
for (int i=1;i<=a; i++) {
if(a%i==0)
c++;
}
if(c == 2)
return true;
else
return false;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Enter two numbers");
int a = in.nextInt();
int b = in.nextInt();
if(check_prime(a) && check_prime(b))
{
if(b-a==2 || a-b==2)
System.out.println("They are twin primes");
else
System.out.println("They are not twin primes");
}
else
System.out.println("They might not be prime numbers");
}
}
"""
这是一个粗略的方法:
import re
b = a.split()
str = b[b.index("class")+1]
javaclass = re.sub("{.*$","",str)
print (javaclass)
...本质上是获取所有单词,并找到第一次出现 "class" 之后的第一个单词。如果您遇到类似
的情况,它还会删除“{”及其后的任何内容class MyClass{
但是,如果一个文件中有多个 类,则需要做更多的工作。
A main class is a class which contains the public static void main function.
如果在您的环境中可行;您可以使用可以解析 Java 源代码的库,例如 plyj
or javalang
:
#!/usr/bin/env python
import javalang # $ pip install javalang
tree = javalang.parse.parse(java_source)
name = next(klass.name for klass in tree.types
if isinstance(klass, javalang.tree.ClassDeclaration)
for m in klass.methods
if m.name == 'main' and m.modifiers.issuperset({'public', 'static'}))
# -> 'second'
如果在 Java 源的顶部有一个包声明,例如 package your_package;
即,如果完整的 class 名称是 your_package.second
那么你可以得到包名称为 tree.package.name
.
或者您可以使用解析器生成器,例如 grako
并指定一个 Java 语法子集,它足以在您的案例中获得 class 名称。如果输入是高度规则的;如果您对代码结构的假设是错误的,您可以尝试使用正则表达式并预计它会失败。
正如我在评论中所说,使用 re.findall()
像这样:
re.findall('class (\w*)', a)
作为函数名,findall()
可以找到所有的class个名字。并在此处使用 \w
将匹配所有 ascii 字母(如果您使用 class MyClass{
,将比 .*
更好)。
关于找到主要 class,使用 re.S
像这样:
for i in re.split('\nclass ', a)[1:]: # will match the main code block and the class name of all classes
if re.search('\n\s*public static void main', i): # check if 'public static void main' in a class
print(re.search('(\w*)', i).group(1)) # and print out the class name
一种更简单的方法,只有一行使用列表理解:
[re.search('(\w*)', i).group(1) for i in re.split('\nclass ', a) if re.search('\n\s*public static void main', i)]
正如您猜想的那样,使用正则表达式可以近似解决问题。但是,请记住一些技巧:
- class 名称不能以空格结尾,因为
MyClass{
是合法且常见的 - 可以在class名称后提供类型参数,例如
MyClass<T>
,编译后的.class
文件名不受此类型参数影响 - 一个文件可以有多个顶层 class,但是不能声明一个 public 而这个 class 不能 与文件同名
- 与文件同名的publicclass可能有内部class(甚至可能是public)但是这些必须在外部 class 声明。
这些提示导致搜索短语 public class
的第一次出现,捕获下一个 运行 个字符,然后寻找空格、{
或 <
字符.
这是我想出来的(可能有点难看):public\s*(?:abstract?)?\s*(?:static?)?\s*(?:final?)?\s*(?:strictfp?)?\s*class\s*(\w.*)\s*,?<.*$
仅使用正则表达式几乎是行不通的。作为为什么它不能的一个基本例子,考虑这个:
public class A {
public static void ImDoingThisToMessYouUp () {
String s = "public static void main (String[] args) {}";
}
}
public class B {
public static void main (String[] args) {}
}
你明白了......Regex 总是会被愚弄,以为他们找到了一些你正在寻找的东西。您必须依赖更高级的库进行解析。
我会选择 J.F。塞巴斯蒂安的回答。