无法使上述正则表达式在sed命令中工作

时间:2020-06-21 03:55:21

标签: regex bash awk sed

我正在尝试使以下正则表达式在bash的sed命令中起作用。

^[^<]?(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*))[^>]?$

我知道正则表达式是正确的,并且按预期运行。所以;不需要任何帮助。我在在线正则表达式测试仪上对其进行了测试,并且按我的期望运行。

请在here.中找到上述正则表达式的演示

我的要求: 我想将每个URL括在<>中。如果URL已经被包含;然后将其附加到结果(如上面的正则表达式链接所示)。

示例输入:(在名为website.txt的文件中)

// List of all legal urls
https://www.google.com/
https://www.fakesite.co.in
https://www.fakesite.co.uk
<https://www.fakesite.co.uk>
<https://www.google.com/>

预期的输出:(在名为output.txt的文件中)

<https://www.google.com/> // Please notice every url is enclosed in the <>.
<https://www.fakesite.co.in>
<https://www.fakesite.co.uk>
<https://www.fakesite.co.uk> // Please notice if the url is already enclosed in <> then it is appended as it is.
<https://www.google.com/>

我在sed中尝试过的事情:

  1. 由于我不精通bash命令;因此,以前我无法在sed中正确捕获该组,但是在阅读了this答案之后;我发现我们需要转义括号才能捕获它。

  2. 某处;我了解到sed(基于GNU)不支持环视,因此我也删除了环视。但这也不起作用。 如果它不支持环顾四周,那么我使用了this正则表达式,它就达到了我的目的。

  3. 然后;这是我最近使用sed命令进行的尝试:

    sed 's@^[^<]?(https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&/=]*))[^>]?$@<\1>@gm;t;d' websites.txt > output.txt
    

我的确切问题:

如何使以上命令正常工作。如果要运行我在上面第3点中附加的命令示例,请参见:您会发现它没有正确替换内容。它只是将websites.txt的内容转储到output.txt中。但是在正则表达式演示中;附件上方的按钮可以正常工作,即将<>内的所有未封闭的网站都包含在内。任何的意见都将会有帮助。 我最好在sed中使用它,但是如果可以的话,我也可以在awk中转换以上命令吗?如果可以的话,请帮我。我将非常有义务。谢谢

3 个答案:

答案 0 :(得分:4)

工作了很长时间后,我使sed命令开始工作。下面是起作用的命令。

Client Product Price 
 1       A      1
 2       A      2
 1       B      5

您可以在here.

中找到该命令的示例实现。

自此,正则表达式已经满足了我正在为其编写此代码的人的要求;我只需要获得有关命令语法的帮助(尽管我们衷心欢迎任何改进);我希望该命令使用相同的正则表达式模式。

我以前不知道并现在了解的事情:

  1. 我对Client Product Price 1 A 1 1 A 1.1 1 A 0.9 2 A 2 2 A 2.2 2 A 1.8 1 B 5 1 B 5.5 1 B 4.5 标志一无所知。现在我知道了; sed -E 's@^[^<]?(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&=]*))[^>]?$@<\1>@gm;t' websites.txt > output.txt 使用POSIX“扩展”语法(“ ERE”)。感谢 @GordonDavisson @Sundeep Further reading.

  2. 我不十分清楚sed不支持环视。但是现在我知道sed不支持环顾四周。感谢 @ dmitri-chubarov Further reading

  3. 我不知道sed也不支持非捕获组。感谢 @Sundeep 解决了这一部分。 Further Reading

  4. 我不知道GNU sed是一种特定的命令行工具。感谢 @oguzismail Further reading.

答案 1 :(得分:2)

关于your answer中的命令:

sed -E 's@^[^<]?(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&=]*))[^>]?$@<\1>@gm;t'

以下是一些注意事项:

您发布的示例输入每行有1个URL,因此sed命令末尾的gm;t无效,因此您的输入不足或脚本错误。

硬编码范围a-zA-Z0-9在不同的语言环境中包含不同的字符。如果要包括所有(且仅包括)小写字母,大写字母和数字,则应将a-zA-Z0-9替换为POSIX字符类[:alnum:]。因此,要么更改为使用与语言环境无关的字符类,要么根据您对正则表达式中要匹配的字符的要求,在命令行上指定所需的语言环境。

与大多数字符一样,字符+在方括号表达式中是文字,因此不应转义-将\+更改为+

方括号表达式[^<]?表示“非<的任何字符出现1或0次”,对于[^>]?则类似,因此如果您的“ url”开头包含随机字符/ end将被接受,例如:

echo 'xhttp://foo.bar%' | sed -E 's@^[^<]?(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&=]*))[^>]?$@<\1>@gm;t'
<http://foo.bar%>

认为,您打算使用<?>?而不是[^<]?[^>]?

您的正则表达式将允许不包含字母的“ url”:

echo 'http://=.9' | gsed -E 's@^[^<]?(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&=]*))[^>]?$@<\1>@gm;t'
<http://=.9>

如果您编辑问题以提供更真实的代表性样本输入和预期输出(包括您不想想要匹配的案例),那么我们可以根据有效内容的快速谷歌为您提供帮助网址似乎是您的正则表达式禁止使用的几个有效URL,以及允许使用的几个无效的URL,因此您可能想在带有url或类似标签(带有您目前拥有的标签可以帮助您实现正则表达式,但可能会有更好的人来帮助您定义正则表达式。

答案 2 :(得分:1)

如果输入文件只是注释,后面是URL列表,请尝试:

sed '1d;s/^[^<]/<&/;s/[^>]$/&>/' websites.txt

输出:

<https://www.google.com/>
<https://www.fakesite.co.in>
<https://www.fakesite.co.uk>
<https://www.fakesite.co.uk>
<https://www.google.com/>