regex 使用正则表达式从字符串中提取文本

a8jjtwal  于 2023-06-07  发布在  其他
关注(0)|答案(3)|浏览(170)

我需要使用正则表达式从字符串中提取文本。示例:

//localhost:8000/pmp/pml/vault/
//localhost:8000/pmp/bom/vault/
//localhost:8000/pmp/parts/advancedsearch/

该字符串可能是不同的本地主机号,或者前半部分可能是完全不同的地址。我需要从'/pmp/'解压缩到下面的斜杠。所以:

/pmp/pml/
/pmp/bom/
/pmp/parts/

我可以使用什么正则表达式来提取该文本。另外,请提供正则表达式的每个组件的详细信息,因为我正在尝试学习这个,而不仅仅是得到答案。
我有下面的正则表达式,但它只适用于字符串在localhost号之后拆分的情况。我也不知道它的任何一部分是什么意思:

`/[^/]*/([^/]*)/`
wf82jlnq

wf82jlnq1#

你不需要Regex来做所有的事情。正则表达式很难理解,很难维护,而且对于很多事情都有更好的解决方案。

from urllib.parse import urlparse
print(urlparse("//localhost:8000/pmp/parts/advancedsearch/"))

这段代码让每个人都清楚地知道你正在解析一个URL。Regex不传达此消息。
输出:

ParseResult(scheme='', netloc='localhost:8000', path='/pmp/parts/advancedsearch/', params='', query='', fragment='')

如您所见,path是您接下来要处理的内容,例如:

from urllib.parse import urlparse
url = urlparse("//localhost:8000/pmp/parts/advancedsearch/")
dirs = url.path.split("/")
print(f"/{dirs[1]}/{dirs[2]}/")
kh212irz

kh212irz2#

这将跳过主机名+端口号,并捕获紧随其后的任何/pmp/someword/

import re

pmp_re = re.compile(r"^//localhost:\d+(/pmp/\w+/)")
if match := pmp_re.search(url):
    print(match[1])

^克拉锚强制任何匹配从开头开始,()括号定义匹配组#1。当查找\d igit或\w ord字符时,+坚持一个或多个匹配。
https://regex101.com/r/KsOaBQ/1
这个正则表达式是脆弱的,因为端口80可能输出为localhost:80/或只是localhost/。我们 * 可以 * 使用?表示零或一,*表示零或多个匹配,使冒号和数字成为可选的:

pmp_re = re.compile(r"^//localhost:?\d*(/pmp/\w+/)")

但最好调用urlparse(),然后处理它返回的path
当我们研究该正则表达式的最后一部分/\w+/时,值得注意的是/斜杠不是\w顺序字符;它既不是字母数字,也不是_下划线。我们 * 可以 * 使用一个花哨的/[^/]+/的“非斜杠”正则表达式,但这样可读性会差很多,所以我建议如果可能的话,你应该避免走这条路。人们更容易从正面而不是负面的Angular 来解读事物。还有一些花哨的“lazy”修饰符,如/.+?/,但这同样不会提高初学者的代码可读性。

myzjeezk

myzjeezk3#

您可以将 regex 尝试从/[^/]*/([^/]*)/稍微调整为//[^/]+(/[^/]+/[^/]+/).*

  • //:匹配开头的文本双斜杠
  • [^/]+:匹配任何字符序列(* 不同于斜杠 *)
  • (/[^/]+/[^/]+/):匹配所需的部分/路径封闭并形成一个组
  • .*:匹配任意字符序列(* 零或更多 *)

Regex:[ demo ]
测试/输出:

import re

list_of_urls = [
    "//localhost:8000/foo/pml/vault/",
    "//localhost:8000/bar/bom/vault/",
    "//localhost:8000/baz/parts/advancedsearch/",
]

def get_path(url):
    m = re.search(r"//[^/]+(/[^/]+/[^/]+/).*", url)
    return m.group(1) if m else None
for url in list_of_urls:
    print(get_path(url))

/foo/pml/
/bar/bom/
/baz/parts/

相关问题