我试图使用sed来清理url行来提取域。
所以从:
http://www.suepearson.co.uk/product/174/71/3816/
我想要:
http://www.suepearson.co.uk/
(不管后面有没有斜杠,都没有关系)
我试过:
sed 's|\(http:\/\/.*?\/\).*|\1|'
And(转义非贪婪量词)
sed 's|\(http:\/\/.*\?\/\).*|\1|'
但我似乎不能让非贪婪量词(?)工作,所以它总是匹配整个字符串。
不幸的是,如前所述,sed不支持这一点。
为了克服这个问题,我建议使用次优方法(实际上甚至更好),使用类似vim sed的功能。
在.bash-profile中定义
vimdo() { vim $2 --not-a-term -c "$1" -es +"w >> /dev/stdout" -cq! ; }
这将创建无头vim来执行命令。
现在你可以这样做:
回声路径美元| vimdo“% s_ \ c: [a-zA-Z0-9 \ \ /] python (a-zA-Z0-9 \ {-} \\/]\{-}:__ g”,
过滤掉$PATH中的python。
使用-在vimdo中从管道中输入。
而大多数语法是相同的。Vim具有更高级的特性,并且使用\{-}是非贪婪匹配的标准。参见帮助regexp。
下面的解决方案适用于匹配/使用multiply present(链式;串联;复合)HTML或其他标签。例如,我想编辑HTML代码以删除串联出现的<span>标记。
问题:常规sed正则表达式贪婪地匹配从第一个到最后一个的所有标记。
解决方案:非贪婪模式匹配(每个讨论在这个线程的其他地方;例如,https://stackoverflow.com/a/46719361/1904943)。
例子:
echo '<span>Will</span>This <span>remove</span>will <span>this.</span>remain.' | \
sed 's/<span>[^>]*>//g' ; echo
This will remain.
解释:
S /<span>:查找<span>
[^>]:后面跟着不是>的任何东西
*>:直到你找到>
//g:将任何这样的字符串替换为空。
齿顶高
我试图清理url,但我遇到了困难匹配/排除一个词- href -使用上面的方法。我简要地研究了反向查找(正则表达式来匹配不包含单词的行),但这种方法似乎过于复杂,并没有提供令人满意的解决方案。
我决定用'(反标记)替换href,做正则表达式替换,然后用href替换'。
示例(为便于阅读,此处格式化):
printf '\n
<a aaa h href="apple">apple</a>
<a bbb "c=ccc" href="banana">banana</a>
<a class="gtm-content-click"
data-vars-link-text="nope"
data-vars-click-url="https://blablabla"
data-vars-event-category="story"
data-vars-sub-category="story"
data-vars-item="in_content_link"
data-vars-link-text
href="https:example.com">Example.com</a>\n\n' |
sed 's/href/`/g ;
s/<a[^`]*`/\n<a href/g'
<a href="apple">apple</a>
<a href="banana">banana</a>
<a href="https:example.com">Example.com</a>
解释:基本如上。在这里,
S /href/ ':将href替换为'(反引号)
s/<a:查找URL开头
[^ ']:后面跟着任何不是'(反撇号)
* ':直到你找到一个'
/<a href/g:用<a href替换每一个找到的
您还应该考虑没有匹配界限的情况。你是否想输出这一行。如果不匹配,我这里的示例不会输出任何内容。
你需要前缀到第三个/,所以选择两次字符串的任何长度不包含/和后面的/,然后字符串的任何长度不包含/,然后匹配/后面的任何字符串,然后打印选择。这个想法适用于任何单个的char delims。
echo http://www.suepearson.co.uk/product/174/71/3816/ | \
sed -nr 's,(([^/]*/){2}[^/]*)/.*,\1,p'
使用sed命令,您可以快速删除前缀或delim选择,如:
echo 'aaa @cee: { "foo":" @cee: " }' | \
sed -r 't x;s/ @cee: /\n/;D;:x'
这比一次吃焦肉快多了。
如果之前匹配成功,跳转到标签。在第一道线/之前加\n。移除到第一个\n。如果添加了\n,则跳转到结束并打印。
如果有开始和结束delim,很容易删除结束delim,直到你到达你想要的第n -2个元素,然后做D技巧,在结束delim后删除,如果不匹配跳转到删除,在开始delim和打印之前删除。这仅在开始/结束分隔成对出现时有效。
echo 'foobar start block #1 end barfoo start block #2 end bazfoo start block #3 end goo start block #4 end faa' | \
sed -r 't x;s/end//;s/end/\n/;D;:x;s/(end).*/\1/;T y;s/.*(start)/\1/;p;:y;d'