sed 忽略模式并匹配同一行中的模式

sed to ignore a pattern as well as match a pattern in same line

输入文件

<a href="perl.html">perl</a>     <a href="http://zoidberg.sourceforge.net/out.html">http://zoidberg.sourceforge.net</a>
<a href="zoiduser.html">zoiduser</a>    <a href="perl.html">perl</a>     <a href="http://zoidberg.sourceforge.net/sample.html">http://zoidberg.sourceforge.net</a>

我只需要从上面的文件 URL 下面删除 .HTML 扩展名:

<a href="perl.html">perl</a>
<a href="zoiduser.html">zoiduser</a>

这样最终的输出应该是这样的:

<a href="perl">perl</a>     <a href="http://zoidberg.sourceforge.net/out.html">http://zoidberg.sourceforge.net</a>
<a href="zoiduser">zoiduser</a>    <a href="perl.html">perl</a>     <a href="http://zoidberg.sourceforge.net/sample.html">http://zoidberg.sourceforge.net</a>

这就是我正在做的事情:

sed '/"http\|"www\|"mailto/ ! s|\(.html\)||g' file

但它会在匹配第一个模式后立即忽略该行,即避免 URL 以“http|”www|“mailto”开头。

您可以使用

sed -E 's/("(http|www|mailto)[^"]*")|\.html//g' file

详情:

  • -E - 启用 POSIX ERE 语法
  • ("(http|www|mailto)[^"]*") - 第 1 组 (</code>):<code>" 然后是 httpwwwmailto 然后是零或 " 以外的更多字符,然后是 "
  • | - 或
  • \.html - .html 字符串。

替换为第 1 组值。

online demo:

#!/bin/bash
s='<a href="perl.html">perl</a>     <a href="http://zoidberg.sourceforge.net/out.html">http://zoidberg.sourceforge.net</a>
<a href="zoiduser.html">zoiduser</a>    <a href="perl.html">perl</a>     <a href="http://zoidberg.sourceforge.net/sample.html">http://zoidberg.sourceforge.net</a>'
sed -E 's/("(http|www|mailto)[^"]*")|\.html//g' <<< "$s"

输出:

<a href="perl">perl</a>     <a href="http://zoidberg.sourceforge.net/out.html">http://zoidberg.sourceforge.net</a>
<a href="zoiduser">zoiduser</a>    <a href="perl">perl</a>     <a href="http://zoidberg.sourceforge.net/sample.html">http://zoidberg.sourceforge.net</a>

不建议使用 shell 实用程序(如 sed、awk、perl 等)来解析 HTML。但是如果你真的必须使用某些关键字的否定,那么我建议这样做 perl:

perl -pe 's/"(?!www|http|mailto)([^"]+)\.html/"/g' f.html

<a href="perl">perl</a>     <a href="http://zoidberg.sourceforge.net/out.html">http://zoidberg.sourceforge.net</a>
<a href="zoiduser">zoiduser</a>    <a href="perl">perl</a>     <a href="http://zoidberg.sourceforge.net/sample.html">http://zoidberg.sourceforge.net</a>
如果这些关键字刚好出现在 "

之后,

(?!www|http|mailto) 是使匹配失败的否定前瞻

仅使用您显示的示例,请尝试以下 awk 代码。简单的解释是,检查行中是否包含 <a href="(http|mailto|www): 并且如果此条件为真,则使用 sub 函数首先替换 .html" 出现 "> 然后打印该行,next 将跳过不满足条件的打印行。1 将打印不满足条件的行。

awk '/<a href="(http|mailto|www):/ && sub(/.html">/,"\">"){print;next} 1' Input_file