我正在尝试从字符串中分离街道名称、门牌号和信箱号。
假设字符串是 "SomeStreet 59A"
对于这种情况,我已经有了正则表达式的解决方案。我正在使用这个功能:
address.split(/([0-9]+)/) //output ["SomeStreet","59","A"]
我现在遇到的问题是某些地址的格式很奇怪。意思是,上述方法不适合像这样的字符串:
"Somestreet 59-65" // output ["SomeStreet", "59", "-", "65"] Not good
我对这种情况的问题是,如何对数字进行分组以获得这个所需的输出:
["Somestreet", "59-65"]
另一个奇怪的例子是:
"6' SomeStreet 59" // here "6' Somestreet" is the exact street-name.
预期输出:
["6' Somestreet", "59"]
"6' Somestreet 324/326 A/1" // Example with box number
预期输出:
["6' Somestreet", "324/326", "A/1"]
请记住,这必须在一个可执行函数中才能循环遍历我拥有的所有地址。
要支持问题中列出的所有字符串格式,您可以使用
.match(/^(.*?)\s+(\d+(?:[-.\/]\d+)?)(?:\s*(\S.*))?$/)
.match(/^(.*)\s+(\d+(?:[-.\/]\d+)?)(?:\s*(\S.*))?$/)
请参阅 正则表达式演示。
详情:
^
- 字符串的开头(.*?)
- 第 1 组:除了换行符之外的任何零个或多个字符,尽可能少(如果您需要将最后一个数字匹配为第 2 组,即 Number
,则需要使用 .*
,a贪婪变体)\s+
- 一个或多个空格(\d+(?:[-.\/]\d+)?)
- 第 2 组:一位或多位数字(可选)后跟 -
/.
//
,然后是一位或多位数字(?:\s*(\S.*))?
- 可选出现零个或多个空格,以及 - 第 3 组 - 非空格字符和字符串的其余部分$
- 字符串结尾。查看 JavaScript 演示:
const texts = ['SomeStreet 59A','Somestreet 59-65',"6' SomeStreet 59", 'Somestreet 1.1', 'Somestreet 65 A/1', "6' Somestreet 324/326 A/1"];
const rx = /^(.*?)\s+(\d+(?:[-.\/]\d+)?)(?:\s*(\S.*))?$/;
for (const text of texts) {
const [_, street, number, box] = text.match(rx);
console.log(text, '=>', {"Street":street, "Number":number, "Box":box});
}
如果您不介意之后稍微修剪一下字符串,这里有一个解决方案:
.split(/(?= \d|\D+$)/)
或同时考虑
65 A/1
或 324/326 A/1
.split(/(?= \d|\D+$|(?<!\D) )/)
[
"Some Street 59A",
"Some Street 59-69",
"Some Street 1.1",
"6' Street 45b",
"6' Some street 324/326 A/1",
"Some Street 65 A/1",
"42th Stack ave. 59-69",
].forEach(str => console.log( str.split(/(?= \d|\D+$|(?<!\D) )/) ));
如果您想保留 number 即:
59A
作为一个整体,这里有另一个简单的解决方案:
.split(/(?= \d| [\w\d/]+$)/);
[
"Some Street 59A",
"Some Street 59-69",
"Some Street 1.1",
"6' Street 45b",
"6' Some street 324/326 A/1",
"Some Street 65 A/1",
"42th Stack ave. 59-69",
].forEach(str => console.log( str.split(/(?= \d| [\w\d/]+$)/) ));
<xsl:template match="/">
<xsl:variable name="address" select="'123 Main Street, Springfield, IL 62704, USA'"/>
<xsl:call-template name="split-address">
<xsl:with-param name="address" select="$address"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="split-address">
<xsl:param name="address"/>
<xsl:choose>
<xsl:when test="string-length($address) > 35">
<xsl:variable name="part1" select="substring($address, 1, 35)"/>
<xsl:variable name="lastSpace1" select="lastIndexOf($part1, ' ')"/>
<xsl:variable name="finalPart1" select="substring($part1, 1, $lastSpace1)"/>
<xsl:variable name="remaining1" select="substring($address, string-length($finalPart1) + 1)"/>
<xsl:variable name="part2" select="substring($remaining1, 1, 35)"/>
<xsl:variable name="lastSpace2" select="lastIndexOf($part2, ' ')"/>
<xsl:variable name="finalPart2" select="substring($part2, 1, $lastSpace2)"/>
<xsl:variable name="finalPart3" select="normalize-space(substring($remaining1, string-length($finalPart2) + 1))"/>
<xsl:text>Part 1: </xsl:text>
<xsl:value-of select="$finalPart1"/>
<xsl:text> </xsl:text>
<xsl:text>Part 2: </xsl:text>
<xsl:value-of select="$finalPart2"/>
<xsl:text> </xsl:text>
<xsl:text>Part 3: </xsl:text>
<xsl:value-of select="$finalPart3"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>Part 1: </xsl:text>
<xsl:value-of select="$address"/>
<xsl:text> </xsl:text>
<xsl:text>Part 2: </xsl:text>
<xsl:text> </xsl:text>
<xsl:text>Part 3: </xsl:text>
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Function to find the last index of a character -->
<xsl:function name="lastIndexOf">
<xsl:param name="str"/>
<xsl:param name="char"/>
<xsl:variable name="position" select="string-length($str)"/>
<xsl:variable name="index" select="0"/>
<xsl:for-each select="1 to $position">
<xsl:variable name="currentChar" select="substring($str, ., 1)"/>
<xsl:if test="$currentChar = $char">
<xsl:variable name="currentIndex" select="."/>
<xsl:variable name="index" select="$currentIndex"/>
</xsl:if>
</xsl:for-each>
<xsl:value-of select="$index"/>
</xsl:function>