【问题标题】:Split filename into groups将文件名分成组
【发布时间】:2019-11-27 09:59:54
【问题描述】:

输入:

“MyPrefix_CH-DE_ProductName.pdf”

期望的输出:

["MyPrefix", "CH", "DE", "ProductName"]

CH 是一个国家代码,它应该来自一个预定义的列表,例如。 ["CH", "IT", "FR", "GB"]

编辑:前缀也可以包含 _ 和 - 但不能包含 CH 或 DE。

DE 是一个语言代码,它应该来自一个预定义的列表,例如。 ["EN", "IT", "FR", "DE"]

我该怎么做?

我在这里寻找基于正则表达式的解决方案。

【问题讨论】:

  • String#split() ?
  • 使用正则分割文件名,filename.split("[_-]")
  • 前缀和产品名称可以包含下划线或破折号吗?如果没有,请拆分这些字符。如果可以,请使用正则表达式,其中您使用交替表示可能的国家/地区代码和语言代码,它们周围的下划线,捕获将作为您的前缀的捕获组中的前面以及将作为您的产品名称的捕获组中的后面的内容
  • 您的任何预定义列表项(语言/国家/地区)是否也可以出现在您的产品名称中,例如ITALIAN有什么?
  • 不,幸运的是。

标签: java regex


【解决方案1】:

我假设扩展名总是 pdf

String str = "MyPref_ix__CH-DE_ProductName.pdf";

String regex = "(.*)_(CH|IT|FR|GB)-(EN|IT|FR|DE)_(.*)\\.pdf";
Pattern pattern = Pattern.compile(regex);

Matcher matcher = pattern.matcher(str);
String[] res = new String[4];

if(matcher.matches()) {
    res[0] = matcher.group(1);
    res[1] = matcher.group(2);
    res[2] = matcher.group(3);
    res[3] = matcher.group(4);
}

【讨论】:

  • 不错的答案,但我会删除扩展始终是 PDF 的假设,您的代码似乎不需要它来工作,删除它会使您的解决方案适用于任何扩展。
  • 这里如果扩展名不是pdf,那么if条件会失败,可以修改正则表达式包含任意扩展名
  • @Aaron 是对的,但我仍然接受它,因为这个概念是正确的,而且他的速度稍快。
【解决方案2】:

你可以试试下面的

String input = "MyPrefix_CH-DE_ProductName.pdf";

String[] segments = input.split("_");


String prefix = segments[0];
String countryCode = segments[1].split("-")[0];
String languageCode = segments[1].split("-")[1];
String fileName = segments[2].substring(0, segments[2].length() - 4);

System.out.println("prefix " + prefix);
System.out.println("countryCode " + countryCode);
System.out.println("languageCode " + languageCode);
System.out.println("fileName " + fileName);

【讨论】:

  • 查看编辑:前缀可以包含 - 和 _。抱歉更改规格:)
【解决方案3】:

此代码使用返回的结果进行拆分并创建一个对象,更多的是 OOP。

package com.local;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        List<String> countries = Arrays.asList("CH", "IT", "FR", "GB");
        List<String> languages  = Arrays.asList("EN", "IT", "FR", "DE");
        String filename = "MyPrefix_CH-DE_ProductName.pdf";
        //Remove prefix
        filename = filename.split("\\.")[0];
        List<String> result = Arrays.asList(filename.split("[_\\-]"));

        FileNameSplitResult resultOne = new FileNameSplitResult(result.get(0), result.get(1), result.get(2), result.get(3));

        System.out.println(resultOne);
    }

    static class FileNameSplitResult{
        String prefix;
        String country;
        String language;
        String productName;

        public FileNameSplitResult(String prefix, String country, String language, String productName) {
            this.prefix = prefix;
            this.country = country;
            this.language = language;
            this.productName = productName;
        }

        @Override
        public String toString() {
            return "FileNameSplitResult{" +
                    "prefix='" + prefix + '\'' +
                    ", country='" + country + '\'' +
                    ", language='" + language + '\'' +
                    ", productName='" + productName + '\'' +
                    '}';
        }
    }
}

执行结果:

FileNameSplitResult{prefix='MyPrefix', country='CH', language='DE', productName='ProductName'}

【讨论】:

    【解决方案4】:

    你可以使用 String.split 两次,这样你就可以先用 '_' 分割得到 CH-DE 字符串,然后用 '-' 分割得到 CountryCode 和 LanguageCode。

    编辑后更新,输入包含“_”和“-”:

    以下代码扫描输入字符串以查找国家/地区匹配项。我将输入更改为“My-Pre_fix_CH-DE_ProductName.pdf”

    检查以下代码:

     public static void main(String[] args) {
            String [] countries = {"CH", "IT", "FR", "GB"};
            String input = "My-Pre_fix_CH-DE_ProductName.pdf";
            //First scan to find country position
            int index = -1;
            for (int i=0; i<input.length()-4; i++){
                for (String country:countries){
                    String match = "_" + country + "-";
                    String toMatch = input.substring(i, match.length()+i);
                    if (match.equals(toMatch)){
                        //Found index
                        index=i;
                        break;
                    }
                }
            }
            String prefix = input.substring(0,index);
            String remaining = input.substring(index+1);//remaining is CH-DE_ProductName.pdf
            String [] countryLanguageProductCode = remaining.split("_");
            String country = countryLanguageProductCode[0].split("-")[0];
            String language = countryLanguageProductCode[0].split("-")[1];
            String productName = countryLanguageProductCode[1].split("\\.")[0];
            System.out.println("[\"" + prefix +"\", \"" + country + "\", \"" + language +"\", \"" + productName+"\"]");
    
        }
    

    它输出:

    ["My-Pre_fix", "CH", "DE", "ProductName"]
    

    【讨论】:

    • 查看编辑:前缀可以包含 - 和 _。抱歉更改规格:)
    【解决方案5】:

    您可以使用以下正则表达式:

    ^(.*?)_(CH|IT|FR|GB)-(EN|IT|FR|DE)_(.*)$
    

    Java 代码:

    Pattern p = Pattern.compile("^(.*?)_(CH|IT|FR|GB)-(EN|IT|FR|DE)_(.*)$");
    Matcher m = p.matcher(input);
    if (m.matches()) {
        String[] result = { m.group(1), m.group(2), m.group(3), m.group(4) };
    }
    

    你可以try it here。

    请注意,如果前缀可以包含像 _CH-EN_ 这样的子字符串,它仍然会失败,而且我认为除了清理输入之外没有什么可以做的了。

    【讨论】:

      【解决方案6】:

      另一种选择,与@billal GHILAS 和@Aaron 的答案几乎相同,但使用命名组。我发现它对我自己或其他人来说很方便,他们会在一段时间后立即查看我的代码,看看我的正则表达式做了什么。命名组更容易。

      String str = "My_Prefix_CH-DE_ProductName.pdf";
      Pattern filePattern = Pattern.compile("(?<prefix>\\w+)_"
                                            + "(?<country>CH|IT|FR|GB)-" 
                                            + "(?<language>EN|IT|FR|DE)_" 
                                            + "(?<product>\\w+)\\.");
      Matcher file = filePattern.matcher(str);
      file.find();
      System.out.println("Prefix: " + file.group("prefix"));
      System.out.println("Country: " + file.group("country"));
      System.out.println("Language: " + file.group("language"));
      System.out.println("Product: " + file.group("product"));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-14
        • 1970-01-01
        • 1970-01-01
        • 2022-11-16
        • 1970-01-01
        • 2013-08-15
        • 1970-01-01
        相关资源
        最近更新 更多