mer*_*011 9 regex awk sed regex-negation regex-lookarounds
我正在尝试编写一个sed脚本,它将捕获文本文件中的所有"裸"URL并将其替换为<a href=[URL]>[URL]</a>."裸"是指未包含在锚标记内的URL.
我最初的想法是,我应该匹配在他们面前没有"或"的URL,并且在他们之后也没有<或a".然而,我在表达"不要在前面或后面"的概念时遇到了困难,因为据我所知,sed没有前瞻或后视.
样本输入:
[Beginning of File]http://foo.bar arbitrary text
http://test.com other text
<a href="http://foobar.com">http://foobar.com</a>
Nearing end of file!!! http://yahoo.com[End of File]
Run Code Online (Sandbox Code Playgroud)
样本期望输出:
[Beginning of File]<a href="http://foo.bar">http://foo.bar</a> arbitrary text
<a href="http://test.com">http://test.com</a> other text
<a href="http://foo.bar">http://foo.bar</a>
Nearing end of file!!! <a href="http://yahoo.com">http://yahoo.com</a>[End of File]
Run Code Online (Sandbox Code Playgroud)
注意第三行未经修改,因为它已经在里面<a href>.另一方面,第一行和第二行都被修改.最后,请注意所有非URL文本都是未修改的.
最终,我想做的事情如下:
sed s/[^>"](http:\/\/[^\s]\+)/<a href="\1">\1<\/a>/g 2-7-2013
Run Code Online (Sandbox Code Playgroud)
我首先验证以下内容是否正确匹配并删除了一个URL:
sed 's/http:\/\/[^\s]\+//g'
Run Code Online (Sandbox Code Playgroud)
然后我尝试了这个,但它无法匹配从文件/输入开头开始的URL:
sed 's/[^\>"]http:\/\/[^\s]\+//g'
Run Code Online (Sandbox Code Playgroud)
有没有办法在sed中解决这个问题,可以通过模拟lookbehind/lookahead,还是明确匹配文件的开头和文件结尾?
sed 是一个出色的工具,可以在单行上进行简单替换,对于任何其他文本操作问题只需使用 awk。
检查我在下面的 BEGIN 部分中使用的与 URL 匹配的正则表达式的定义。它适用于您的示例,但我不知道它是否捕获所有可能的 URL 格式。即使它没有,但它可能足以满足您的需求。
$ cat file
[Beginning of File]http://foo.bar arbitrary text
http://test.com other text
<a href="http://foobar.com">http://foobar.com</a>
Nearing end of file!!! http://yahoo.com[End of File]
$
$ awk -f tst.awk file
[Beginning of File]<a href="http://foo.bar">http://foo.bar</a> arbitrary text
<a href="http://test.com">http://test.com</a> other text
<a href="http://foobar.com">http://foobar.com</a>
Nearing end of file!!! <a href="http://yahoo.com">http://yahoo.com</a>[End of File]
$
$ cat tst.awk
BEGIN{ urlRe="http:[/][/][[:alnum:]._]+" }
{
head = ""
tail = $0
while ( match(tail,urlRe) ) {
url = substr(tail,RSTART,RLENGTH)
href = "href=\"" url "\""
if (index(tail,href) == (RSTART - 6) ) {
# this url is inside href="url" so skip processing it and the next url match.
count = 2
}
if (! (count && count--)) {
url = "<a " href ">" url "</a>"
}
head = head substr(tail,1,RSTART-1) url
tail = substr(tail,RSTART+RLENGTH)
}
print head tail
}
Run Code Online (Sandbox Code Playgroud)