首页 > 解决方案 > 如何使用 Powershell 打印包含匹配字符串的整个函数?

问题描述

我需要在 .java 文件中找到某个字符串并仅选择包含该字符串的函数。

示例代码:

/*    */ package com.mypackage.servlets;

/*    */ import javax.servlet.http.HttpServletRequest;
/*    */ import javax.servlet.http.HttpServletResponse;


/*    */ public class GetChallengeServlet
/*    */   extends HttpServlet
/*    */ {

            public  int hello(){

            }

/*    */   public void doGet(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse) throws ServletException, IOException {}
/*    */   
/* 22 */   String userName = null;
/*    */ 
            public  int hello2(){

            }
/*    */   
/*    */   public void service(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse) throws ServletException, IOException {
/* 26 */     this.userName = null;
/* 27 */     String str1 = null;
/* 28 */     String str2 = null;
/* 29 */     HttpSession httpSession = paramHttpServletRequest.getSession(false);
/* 30 */     PrintWriter printWriter = null;

/*    */   }
/*    */ }
  1. 我需要递归打印具有参数“HttpServletRequest”的整个函数
  2. 我需要递归打印具有字符串“getSession”的整个函数

即在这里,我只需要打印“doGet”和“service”函数。

我可以使用任何高级正则表达式来实现这一点吗?还有其他逻辑可以实现相同的目标吗?

实际上,我需要在 Powershell、Bash 和 Python 中编写代码。我希望该解决方案适用于所有语言。

我在Powershell下面试过

$input = gc -Raw 'GetChallengeServlet.java'
$sections = $input | select-string -AllMatches '(?smi)(public.*\(HttpServlet.*?(public|private|protected))'
$sections.Matches | foreach {$_.Value}

但它选择:

public class GetChallengeServlet
/*    */   extends HttpServlet
/*    */ {

            public  int hello(){

            }

/*    */   public void doGet(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse) throws ServletException, IOException {}
/*    */   
/* 22 */   String userName = null;
/*    */ 
            public

这是不正确的。

标签: regexpowershell

解决方案


  1. 我需要递归打印具有参数“HttpServletRequest”的整个函数

此正则表达式适用于您的示例(查看结果):

public.*?HttpServletRequest(?s).*?{.*?}
  1. 我需要递归打印具有字符串“getSession”的整个函数

此正则表达式适用于您的示例(查看结果):

public\s(?!class)(?s)[^}]+{[^}]+getSession[^}]+}

正如我所指出的,这些正则表达式适用于您的示例。如果您的代码变得更复杂,例如在函数中包含嵌套代码块,它们可能不再起作用。

如果您希望正则表达式为函数中的每个可能的代码片段做好准备,那么您将非常接近解析。你将不得不找到平衡的括号等等。在我看来,这对你的问题来说太过分了。您可能应该使用一个将所有函数分开的解析器,然后您可以使用正则表达式来仅识别所需的函数。


示例如何在 PowerShell 中使用正则表达式:

$content = Get-Content .\GetChallengeServlet.java -Raw
Select-String -InputObject $content -Pattern 'public.*?HttpServletRequest(?s).*?{.*?}' -AllMatches | ForEach-Object {$_.Matches.Value}

输出:

public void doGet(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse) t
hrows ServletException, IOException {}
public void service(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse)
 throws ServletException, IOException {
/* 26 */     this.userName = null;
/* 27 */     String str1 = null;
/* 28 */     String str2 = null;
/* 29 */     HttpSession httpSession = paramHttpServletRequest.getSession(false);
/* 30 */     PrintWriter printWriter = null;

/*    */   }

提示进一步处理更复杂的示例,而不是真正解析 java 源代码,您可以执行以下解决方法:将文件分成几部分(当然是通过脚本)

  1. 如果您的文件可能包含多个类定义,则在每个类定义之前拆分
  2. 对于每个类片段,在每个方法定义之前拆分

之后,您将或多或少只有单一方法,不再需要确定它们的目的。然后您可以通过上面提供的正则表达式过滤它们。

仍然会有一个挑战:嵌套在方法中的方法呢?你需要关心他们吗?它会变得更加复杂......


推荐阅读