sed正则表达式不符合预期

时间:2014-08-01 09:44:33

标签: regex sed

我正在尝试用sed操纵yum repofile并且它没有按预期工作。该文件看起来像这样:

[repo id]
name = value
name = value
[repo id]
name = value
name = value

这可能不是最好的方法,但我仍然想知道它为什么不起作用......

首先,我将repo文件转换为一个大字符串:

sed ':a;N;$!ba;s/\n/:::/g' $repofile |

然后,这是不起作用的部分,我想匹配我正在寻找的特定仓库并修剪文件的其余部分。我这样做是通过匹配开头[后跟包含正确repo id的字符串。然后我想匹配其他所有内容,直到下一个开头[在文件中:

sed "s/^.*\(\[${repoid}\].*\[\).*/\1/" >~/trimed_repo

然后我将新行重新放入并继续使用awk进行修改。

sed 's/:::/\n/g' ~/trimed_repo >~/expanded_repo

我遇到的问题是我的正则表达式似乎跳过了所有下一个开头[在与$ repoid配对后的文件中,并且只匹配文件中的最后一个开头。

我尝试使用"懒惰量词"但它完全阻止了正则表达式的匹配。像这样:

sed "s/^.*\(\[${repoid}\].*?\[\).*/\1/" >~/trimed_repo

就像这样:

sed "s/^.*\(\[${repoid}\](.*?)\[\).*/\1/" >~/trimed_repo

答案*

所以在评论中有一些帮助我做了这个有用的工作:

sed "s/^.*\(\[${repoid}\][^[]*\)\[.*/\1/" >~/trimed_repo

我的教训是,我应该说的是匹配所有不是开口的东西[直到找到一个开口[并且这将防止不必要的行为。

有人可以解释为什么这两个选项的行为在这两个实例中有所不同吗? 。*与第一个实例中的文件末尾不匹配。它在下一个指定选项处停止。但在第二种情况下,它不会停止直到最后一次匹配。

我指的是我原来的,破碎的例子:

sed "s/^.*\(\[${repoid}\].*\[\).*/\1/" >~/trimed_repo

2 个答案:

答案 0 :(得分:2)

$ cat file
[foo]
name = 3
name = 17
[bar]
name = 24
name = 5

$ awk -v id="foo" '/\[/{f=index($0,"["id"]")} f' file
[foo]
name = 3
name = 17

$ awk -v id="bar" '/\[/{f=index($0,"["id"]")} f' file
[bar]
name = 24
name = 5

以上只是在找到包含f的行时设置了一个标记(找到[foo]),并在找到包含[的下一行时将其清除。设置f时,会打印该行。

另请注意,与任何可能的sed解决方案不同,上述内容不会受到搜索变量中的RE元字符或分隔符(例如., ?, *, +, /, (, etc.)的影响,因为它正在查找STRING而不是正则表达式。

答案 1 :(得分:0)

您可以使用范围从回购文件中提取匹配的部分。

sed -ne "/\[${repoid}\]/,/\[/{/\[${repoid}\]/p;/\[/!p}" $repofile > ~/trimed_repo