从命令 window 输出中获取特定的子字符串(来自 ping 的时间)

get specific substring from command window output (time from ping)

您好,我正在从命令 windows 执行中获取 ping 信息。我想将该信息读取到我的 Java 代码中。我只想保留和使用时间信息。

这是 ping 命令的示例输出(Java 代码的输入):

    Esecuzione di Ping 10.10.0.161 con 32 byte di dati:
Risposta da 10.10.0.161: byte=32 durata=3ms TTL=64

Statistiche Ping per 10.10.0.161:
    Pacchetti: Trasmessi = 1, Ricevuti = 1, 
    Persi = 0 (0% persi),
Tempo approssimativo percorsi andata/ritorno in millisecondi:
    Minimo = 3ms, Massimo =  3ms, Medio =  3ms

但我只想提取这个:

durata=3ms

这是代码:

Pattern pattern = Pattern.compile(".*?durata=(.*?ms) ",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);               
                Matcher m = null;
                while ((inputLine = in.readLine()) != null) {
                        m = pattern.matcher(inputLine);

                        if (m.find()) {
                            packet.setSendTime(Integer.parseInt(m.group(1)));

                                    piii= m.group(1);
                                    System.out.println(piii);
                        }
                }

编辑

这是我的实际代码,结束macther什么也找不到。

        Runtime r = Runtime.getRuntime();
        Process p = r.exec(pingCmd);

        BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String inputLine;
        while ((inputLine = in.readLine())!= null){
            System.out.println(inputLine);
            pingResult += "\n"+inputLine;
        }

        Pattern pattern = Pattern.compile("durata=(\d+)ms");
        Matcher m = null;

        while ((inputLine = in.readLine()) != null) {
               m = pattern.matcher(inputLine);

               if (m.find()) {
                     packet.setSendTime(Integer.parseInt(m.group(1)));
                     piii= m.group(1);
                     System.out.println("Time: " +piii);
                }
        }

        in.close();

我的输出没有显示我在 System.out.println(piii);

时想要的信息

为什么不通过代码提取持续时间?谢谢

在 OP 编辑​​后进行编辑

问题在于您使用输入流的方式。您遍历它以使用以下代码打印出 ping 命令输出:

    while ((inputLine = in.readLine())!= null){
        System.out.println(inputLine);
        pingResult += "\n"+inputLine;
    }

但您随后尝试使用以下代码进行处理:

    while ((inputLine = in.readLine()) != null) {
           m = pattern.matcher(inputLine);

不幸的是,ping 命令已经完成,您已经处理了它的所有结果(输出并将它们附加到 pingResult)并且您的输入流是空的,所以您永远不会进入第二个循环。

您有几个选择:

  1. 只需删除第一个 while 循环。这意味着您没有在终端上实时看到 ping 命令的输出。
  2. 如果这有问题 - 将以下行移到第二个 while 循环中,然后删除第一个循环。

        System.out.println(inputLine);
    
  3. 另一个选择,如果你真的想保留第一个循环,是使用你在第一个循环中收集的 pingResult 字符串作为第二个循环的输入。

我已经离开下面的部分来回答问题的其他方面,通过 OP 编辑​​解决。


方方面面的完整解释

就你的代码而言,我希望它在你尝试时抛出异常

packet.setSendTime(Integer.parseInt(m.group(1)))

这是因为 m.group(1) 将 return 您的比赛中的第一组 - 这将是(在您的示例中)3ms。由于 3ms 不是纯数字,我希望 parseInt 抛出 NumberFormatException。我试图通过将 ping 输出放入字符串并将 in 初始化为 BufferedReader 读取该字符串来复制您的问题。我得到一个 NumberFormatException

要解决此问题,请更改 Pattern 正则表达式。术语周围的括号定义组(参见 the description of how this works in the API docs)。所以使用

        Pattern pattern = Pattern.compile(".*?durata=(.*?)ms ",Pattern.CASE_INSENSITIVE |
                Pattern.MULTILINE | Pattern.DOTALL);               

请注意右括号位置的微小变化。这样-您的代码应该可以工作。

编辑

添加了对我有用的代码:

public class PingReader
{

    static final String pingOut = "    Esecuzione di Ping 10.10.0.161 con 32 byte"
            + " di dati:\n"
            + "Risposta da 10.10.0.161: byte=32 durata=3ms TTL=64\n\n"
            + "Statistiche Ping per 10.10.0.161:\n"
            + "    Pacchetti: Trasmessi = 1, Ricevuti = 1,\n"
            + "    Persi = 0 (0% persi),\n"
            + "Tempo approssimativo percorsi andata/ritorno in millisecondi:\n"
            + "    Minimo = 3ms, Massimo =  3ms, Medio =  3ms";

    public static void main(String[] args) throws NumberFormatException, IOException
    {
        StringReader inReader = new StringReader(pingOut);
        BufferedReader in = new BufferedReader(inReader);
        String inputLine = "";      

        Pattern pattern = Pattern.compile(".*?durata=(.*?)ms ",Pattern.CASE_INSENSITIVE |
                Pattern.MULTILINE | Pattern.DOTALL);               
        Matcher m = null;
        while ((inputLine = in.readLine()) != null) {
                m = pattern.matcher(inputLine);

                if (m.find()) {
                    int sendTime = (Integer.parseInt(m.group(1)));

                           String piii= m.group(1);
                            System.out.println(piii);
                }
        }       
    }
}

编辑 2

与正则表达式一样,有很多方法可以得到您想要的。

您可以将以下内容替换为您的模式,可能更容易理解正在发生的事情:

Pattern pattern = Pattern.compile("durata=(\d+)ms");

在这种情况下,所需的字符串是已知大小写(ping 将始终输出小写),因此不需要 Pattern.CASE_INSENSITVE,我们不匹配行尾,因此 Pattern.MULTLINE不是必需的,并且使用我的新模式,我们只匹配我们感兴趣的位,因此不需要 Pattern.DOTALL

请注意,d 仅匹配数字,+ 号表示我们需要多个数字之一。

这仍然适用于我的示例。