繁体   English   中英

用于解析 Azure Data Lake Storage Gen2 URI 的正则表达式,用于使用 Azurite 进行生产和测试

[英]Regex to parse Azure Data Lake Storage Gen2 URI for production and testing with Azurite

在我的 Java 应用程序中,我使用 Azure Data Lake Storage Gen2 进行存储 ( ABFS )。 在处理文件系统请求的 class 中,我得到一个文件路径作为输入,然后使用一些正则表达式从中提取 Azure 连接信息。

Azure Data Lake Storage Gen2 URI采用以下格式:

abfs[s]://<file_system>@<account_name>.dfs.core.windows.net/<path>/<file_name>

我使用以下正则表达式abfss?://([^/]+)@([^\\.]+)(\\.[^/]+)/?((.+)?)来解析给定的解压文件路径:

  • 文件系统
  • 帐户名称
  • 账户后缀
  • 相对路径(路径 + 文件名)

下面只是一个测试 Java 代码,其中注释说明匹配后每个变量中的结果/值。

private void parsePath(String path) {
    //path = abfs://storage@myaccount.dfs.core.windows.net/selim/test.csv
    Pattern azurePathPattern = Pattern.compile("abfss?://([^/]+)@([^\\.]+)(\\.[^/]+)/?((.+)?)");
    Matcher matcher = azurePathPattern.matcher(path);
    if (matcher.find()) {
        String fileSystem = matcher.group(1); //storage
        String accountName = matcher.group(2); //myaccount
        String accountSuffix = matcher.group(3); //.dfs.core.windows.net
        //relativePath is <path>/<file_name>
        String relativePath = matcher.group(4); //selim/test.csv
    }
}

问题是当我决定使用Azurite时,它是一个 Azure 存储 API 兼容服务器(模拟器),它允许我针对这个模拟器运行单元测试,而不是像 Microsoft 文档中推荐的那样针对实际的 Azure 服务器运行单元测试。

Azurite 使用与 Azure 不同的文件 URI,因此这使我的上述正则表达式无法用于测试目的。 Azurite 文件 URI 的格式如下:

abfs[s]://<file_system>@<local_ip>:<local_port>/<account_name>/<path>/<file_name>

Azurite 默认account_namedevstoreaccount1 ,因此这里是 Azurite 上文件的示例路径:

abfs://storage@127.0.0.1:10000/devstoreaccount1/selim/test.csv

如果通过上述正则表达式解析,这将是 output,导致对 Azurite 服务器的 api 调用不正确:

  • 文件系统:存储(正确)
  • accountName:127(不正确,应该是: devstoreaccount1
  • accountSuffix: .0.0.1:10000 (不正确,应该是空字符串
  • relativePath: devstoreaccount1/selim/test.csv (不正确,应该是selim/test.csv )

是否有可能有一个可以处理两个 URI 或 2 个正则表达式的 1 个正则表达式来解决这个问题

解决方案 1

您可以为此使用单一模式,但您需要检查代码中匹配的组以确定捕获必要详细信息的位置。

正则表达式看起来像

abfss?://(?:([^@/]*)@(\d{1,3}(?:\.\d{1,3}){3}:\d+)/([^/]+)|([^/]+)@([^.]+)(\.[^/]+))(?:/(.+))?

请参阅正则表达式演示 ([^@/]*)@(\d{1,3}(?:\.\d{1,3}){3}:\d+)/([^/]+)替代方法允许捕获文件系统, @之后的 IP 地址部分(带有端口号),以及斜杠之后的帐户名。

Java 代码看起来像

import java.util.*;
import java.util.regex.*;

class Test
{
    public static void main (String[] args) throws java.lang.Exception
    {
        Pattern pattern = Pattern.compile("abfss?://(?:([^@/]*)@(\\d{1,3}(?:\\.\\d{1,3}){3}:\\d+)/([^/]+)|([^/]+)@([^.]+)(\\.[^/]+))(?:/(.+))?");
        String[] inputs = {
            "abfs://storage@myaccount.dfs.core.windows.net/selim/test.csv",
            "abfs://storage@127.0.0.1:10000/devstoreaccount1/selim/test.csv"
        };
        for (String s: inputs) {
            Matcher matcher = pattern.matcher(s);
            if (matcher.find()){
                if (matcher.group(5) != null) { // If original URL is found
                    String fileSystem = matcher.group(4); //storage
                    String accountName = matcher.group(5); //myaccount
                    String accountSuffix = matcher.group(6); //.dfs.core.windows.net
                    String relativePath = matcher.group(7); //selim/test.csv
                    System.out.println(s + ":\nfileSystem: " + fileSystem + "\naccountName: " + accountName + "\naccountSuffix: '" + accountSuffix + "'\nrelativePath:" + relativePath + "\n-----");
                } else { // we have an Azurite URL
                    String fileSystem = matcher.group(1); //storage
                    String accountName = matcher.group(3); //devstoreaccount1
                    String accountSuffix = ""; // empty (or do you need matcher.group(2) to get "127.0.0.1:10000"?)
                    String relativePath = matcher.group(7); //selim/test.csv
                    System.out.println(s + ":\nfileSystem: " + fileSystem + "\naccountName: " + accountName + "\naccountSuffix: '" + accountSuffix + "'\nrelativePath:" + relativePath + "\n-----");
                }
            }
        }
    }
}

Output:

abfs://storage@myaccount.dfs.core.windows.net/selim/test.csv:
fileSystem: storage
accountName: myaccount
accountSuffix: '.dfs.core.windows.net'
relativePath:selim/test.csv
-----
abfs://storage@127.0.0.1:10000/devstoreaccount1/selim/test.csv:
fileSystem: storage
accountName: devstoreaccount1
accountSuffix: ''
relativePath:selim/test.csv

方案二

您可以使用两个不同的正则表达式,如果第一个没有找到匹配项,将尝试第二个。 第一个:

abfss?://([^@/]*)@(\d{1,3}(?:\.\d{1,3}){3}:\d+)/([^/]+)(?:/(.+))?

请参阅此正则表达式演示 第二个:

abfss?://([^/]+)@([^.]+)(\.[^/]+)(?:/(.+))?

请参阅此正则表达式演示 由于这个也匹配第一种类型的 URL,您需要确保以固定顺序运行它们。

请参阅Java 演示

import java.util.*;
import java.util.regex.*;

class Test
{
    public static void main (String[] args) throws java.lang.Exception
    {
        Pattern pattern_azurite = Pattern.compile("abfss?://([^@/]*)@(\\d{1,3}(?:\\.\\d{1,3}){3}:\\d+)/([^/]+)(?:/(.+))?");
        Pattern pattern_original = Pattern.compile("abfss?://([^/]+)@([^.]+)(\\.[^/]+)(?:/(.+))?");
        String[] inputs = {
            "abfs://storage@myaccount.dfs.core.windows.net/selim/test.csv",
            "abfs://storage@127.0.0.1:10000/devstoreaccount1/selim/test.csv",
            "http://www.blahblah.blah"
        };
        for (String s: inputs) {
            Map<String, String> result = null;
            Matcher matcher_azurite = pattern_azurite.matcher(s);
            if (matcher_azurite.find()){
                result = parseMatchResult(matcher_azurite, new int[] {1, 3, -1, 4});
            } else {
                Matcher matcher_original = pattern_original.matcher(s);
                if (matcher_original.find()){
                    result = parseMatchResult(matcher_original, new int[] {1, 2, 3, 4});
                }
            }
            if (result != null) {                        // Now print
                for (String key : result.keySet()) {
                    System.out.println("'" + key + "': '" + result.get(key) + "'");
                }
                System.out.println("----------------");
            } else {
                System.out.println("No match!");
            }
            
        }
    }
    public static Map<String, String> parseMatchResult(Matcher m, int[] indices) {
        Map<String, String> res = new HashMap<String, String>();
        res.put("fileSystem", m.group(indices[0]));
        res.put("accountName", m.group(indices[1]));
        res.put("accountSuffix", indices[2] > -1 ? m.group(indices[2]) : "");
        res.put("relativePath", m.group(indices[3]));
        return res;
    }
}

Output:

'fileSystem': 'storage'
'accountSuffix': '.dfs.core.windows.net'
'accountName': 'myaccount'
'relativePath': 'selim/test.csv'
----------------
'fileSystem': 'storage'
'accountSuffix': ''
'accountName': 'devstoreaccount1'
'relativePath': 'selim/test.csv'
----------------
No match!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM