【问题标题】:How to get substring from string without split?如何在不拆分的情况下从字符串中获取子字符串?
【发布时间】:2019-06-11 10:30:41
【问题描述】:
String str = "internet address : http://test.com Click this!";

我想得到“http://test.com”,所以我这样写。

String[] split = str.split(" ");
for ( int i = 0 ; i < split.length ; i++ ) {
    if ( split[i].contains("http://") ) {
        return split[i];
    }
}

但我认为这是无效的。如何更容易获得?

【问题讨论】:

  • regex 在这种情况下似乎很适合你,但必须仔细阐明模式。
  • 示例字符串的哪一部分是常量,哪一部分是可变的?
  • 为什么您认为您的代码“无效”?您的代码在某些情况下不起作用吗?使用例如的解决方案。正则表达式也很容易变得复杂。

标签: java


【解决方案1】:

你可以使用正则表达式

String str = "internet address : http://test.com Click this!";
Pattern pattern = Pattern.compile("((http|https)\\S*)");
Matcher matcher = pattern.matcher(str);
if (matcher.find())
{
    System.out.println(matcher.group(1));
}

【讨论】:

  • 我认为这个正则表达式是最好的和简单的。非常感谢!
  • 很高兴它能帮到你! :)
【解决方案2】:

我刚刚为此做了一个快速的解决方案。它应该非常适合您。

package Main.Kunal;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class URLOutOfString {

    public static void main(String[] args) {
        String str = "internet address : http://test.com Click this!, internet address : http://tes1t.com Click this!";
        List<String> result= new ArrayList<>();
        int counter = 0;
        final Pattern urlPattern = Pattern.compile(
                "(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)"
                        + "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*"
                        + "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",
                Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

        Matcher matcher = urlPattern.matcher(str);

        while (matcher.find()) {
            result.add(str.substring(matcher.start(1), matcher.end()));
            counter++;
        }

        System.out.println(result);

    }

}

这将在您的字符串中找到所有 URL 并将其添加到 arraylist。您可以根据自己的业务需要使用它。

【讨论】:

    【解决方案3】:

    不清楚输入字符串的结构是否是常量,但是,我会这样做:

        String str = "internet address : http://test.com Click this!";
        // get the index of the first letter of an url
        int urlStart = str.indexOf("http://");
        System.out.println(urlStart);
        // get the first space after the url
        int urlEnd = str.substring(urlStart).indexOf(" ");
        System.out.println(urlEnd);
        // get the substring of the url
        String urlString = str.substring(urlStart, urlStart + urlEnd);
        System.out.println(urlString);
    

    【讨论】:

    • 我选择 indexOf(" ", urlStart) 非常感谢!
    【解决方案4】:

    通常,这可以通过正则表达式或indexOfsubstring 来完成。

    使用正则表达式,可以这样做:

        // This is using a VERY simplified regular expression
        String str = "internet address : http://test.com Click this!";
        Pattern pattern = Pattern.compile("[http:|https:]+\\/\\/[\\w.]*");
        Matcher matcher = pattern.matcher(str);
        if (matcher.find()) {
            System.out.println(matcher.group(0));
        }
    

    你可以在这里阅读为什么它被简化:https://mathiasbynens.be/demo/url-regex - tl;dr:URL 的问题是它们可以有很多不同的有效模式。

    有了split,就有了一种利用Java的URL类的方法:

       String[] split = str.split(" ");
    
        for (String value : split) {
            try {
                URL uri = new URL(value);
                System.out.println(value);
            } catch (MalformedURLException e) {
                // no valid url
            }
        }
    

    您可以在 OpenJDK 源代码here 中检查它们的验证。

    【讨论】:

      【解决方案5】:

      假设您始终使用相同的格式(一些文本:URL 更多文本),这可以工作:

      public static void main(String[] args) throws IOException {
          String str = "internet address : http://test.com Click this!";
          String first = str.substring(str.indexOf("http://"));
          String second = first.substring(0, first.indexOf(" "));
          System.out.println(second);
      }
      

      但更好的是不同答案中建议的正则表达式

      【讨论】:

      • 无需使用substring 两次:使用indexOf(String, int) 重载即可结束。但请记住,您(可能)需要处理没有后续空间的演员表。
      • 哇,这个解决方案太棒了!我觉得我很傻,为什么我不能这样想?安迪·特纳也很棒!
      • @Warak 如果您不确定输入字符串格式 - 正则表达式是 IMO 的最佳方式
      • 当字符串输入不以“”结尾时,我认为这个解决方案并不完美。所以我需要检查'第二'是-1。正则表达式可能更好。
      • @Warak 实际上它会在 URL 之后查找空格,而不考虑输入字符串的结尾。但是肯定正则表达式是最好的方法,只要注意正确的模式
      【解决方案6】:

      在字符串中找到http://,然后前后查找空格:

      int pos = str.indexOf("http://");
      if (pos >= 0) {
        // Look backwards for space.
        int start = Math.max(0, str.lastIndexOf(' ', pos));
      
        // Look forwards for space.
        int end = str.indexOf(' ', pos + "http://".length());
        if (end < 0) end = str.length();
      
        return str.substring(start, end);
      }
      

      【讨论】:

      • 数学课不重吗?比 split 或 regex 有更好的性能吗?
      • 不,当然不是。我的意思是,如果你愿意,可以使用if (start &lt; 0) start = 0;(这与向前看是一致的);但实际上,那是纳米优化。
      • 为什么要寻找向后的空间?当然,您可以从 pos 开始?
      • @TiiJ7 因为 OP 正在搜索字符串包含 http://。如果原始代码是split[i].startsWith("http://"),则无需向后搜索。
      【解决方案7】:

      我对正则表达式的尝试

      String regex = "http?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)";
      String str = "internet address : http://test.com Click this!";
      Pattern pattern = Pattern.compile(regex);
      Matcher matcher = pattern.matcher(str);
      if (matcher.find()) {
          System.out.println(matcher.group(0));
      }
      

      结果:

      http://test.com
      

      来源:here

      【讨论】:

      • 正则表达式。非常感谢!
      • @Warak 我知道您有自己接受的答案,对此我没有任何抱怨。但要注意一点:请记住我提到的关于 but must clarify the pattern carefully 的评论,这就是为什么我将链接放在我的答案中以进行进一步调查/了解选择最适合您的模式的所有风险。
      猜你喜欢
      • 2020-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多