如何仅捕获字符串的开头和结尾,同时避免匹配正则表达式的中间?

问题描述 投票:0回答:2

我试图使用 grep 命令捕获匹配的正则表达式的开头和结尾,但我不希望捕获字符串的中间部分。

这是字符串:

href="file:///home/user/file" added="2023-09-07T21:58:58Z" modified="2023-09-07T22:27:45Z" visited="2023-09-07T21:58:58Z"

我想捕获

<bookmark href="file:///home/user/file"
,排除
 added="2023-09-07T21:58:58Z" modified="2023-09-07T22:27:45Z"
并捕获
visited="2023-09-07T21:58:58Z">

为了做到这一点,我尝试了以下 grep 命令:

$ grep -oP -m 10 'href="file:///.*(?="\sadded=".*visited=").*'

这是标准输出:

href="file:///home/user/file" added="2023-09-07T21:58:58Z" modified="2023-09-07T22:27:45Z" visited="2023-09-07T21:58:58Z">

这不是我正在寻找的捕获的字符串,因为

 added="2023-09-07T21:58:58Z" modified="2023-09-07T22:27:45Z"
存在

我认为前瞻表达式

(?="\sadded=".*visited=")
不会更改字符串匹配位置,这就是为什么下面的
.*
捕获字符串的中间,但我不确定。

regex bash regex-lookarounds
2个回答
0
投票

正则表达式匹配始终是要匹配的字符串的连续子字符串,因此旨在匹配单个模式的

grep
命令不适合该任务。

可以改用awk,将字段分隔符设置为

'='
,将输入输出记录分隔符设置为空格,这样就可以方便地按第一个字段过滤记录了:

awk -F'=' -vRS=' ' -vORS=' ' '$1!~/added|modified/'

演示:https://awk.js.org/?snippet=97Xo5e


0
投票

可以做类似的事情

grep -o -e '^<bookmark href="[^"]*"' -e 'visited="[^"]*"$>' file

但对于更一般的情况,

grep
似乎完全是错误的工具。

sed -n 's/^\(<bookmark href="[^"]*"\).*\(visited="[^"]*"\)$>/\1\n\2/p' file

一如既往,如果您正在处理 HTML / XML,更好的方法是使用实际的 XML 解析器。

© www.soinside.com 2019 - 2024. All rights reserved.