需要sed的正则表达式

时间:2018-02-22 11:03:46

标签: regex sed

我正在尝试创建一个脚本,该脚本将在sources.list(Ubuntu)中启用其他东西启用源存储库。您可能知道或不知道存储库文件的格式是这样的:

deb http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted
# deb-src http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted
# etc.

所以我想启用源存储库(使用deb-src取消注释行),但仅限于未注释的deb行之前的那些。 GNU sed应该是完美的,但我无法做到这一点。 这就是我现在所拥有的:

sed -i 's/^# deb-src/deb-src/gm' /etc/apt/sources.list

我想要的是这样的东西,但它应该只替换注释行而不是所有内容:

sed -i 's/^deb .*$^# deb-src/deb-src/gm' /etc/apt/sources.list

那么有没有办法为sed制作只能替换匹配字符串部分的正则表达式?

3 个答案:

答案 0 :(得分:2)

我个人更喜欢awk/perl来匹配两个连续的行

awk '/^# *deb-src/ && p ~ /^deb /{sub(/^# */, "")} {p=$0} 1'
  • p=$0保存上一行
  • /^# *deb-src/ && p ~ /^deb /如果当前行以评论开头并且 deb-src 且上一行以 deb
  • 开头
  • sub(/^# */, "")删除评论
  • 1以惯用方式打印当前记录,包括所做的任何更改
  • 另请参阅:awk save modifications in place


使用sed,您可能需要类似

的内容
sed '/^deb /{n; /^# *deb-src/ s/# *//p; D}'

sed '$!N; /^deb .*\n# *deb-src/ s/\n# */\n/p; D'

但我不太确定这是否可以处理所有情况。有关详细信息,请参阅https://www.gnu.org/software/sed/manual/sed.html#advanced-sed。只有在模式空间中有多行时,m修饰符才会起作用。默认情况下,sed使用换行作为行分隔符,并且在模式空间中只有单行。手动链接有更多详细信息

答案 1 :(得分:2)

-z之外使用-r

sed -rz -i 's/^(deb .*\s+)^# deb-src/\1deb-src/gm' /etc/apt/sources.list

捕获组是必要的,以便更换它们。

答案 2 :(得分:0)

如果您的sources.list仅由以下行组成:

deb http://................
deb-src http://............

# deb http://...........
# deb-src http://.........

deb http://................
# deb-src http://............

并且您不必删除注释行,您可以通过仅修改以deb开头的未注释的行来创建新的sources.list文件:

grep -A1 "^deb " sources.list | sed "s/# deb-src/deb-src/g"

使用此选项,您只会选择以^deb开头的行和下一行,然后取消注释下一行(以# deb-src开头的那一行)

然后,您可以将输出发送到新文件,然后可以通过sources.list重命名:

grep -A1 "^deb " sources.list | sed "s/# deb-src/deb-src/g" > sources_new && mv -f sources_new sources.list

但是只有在sources.list文件中有这种语法时才会有效。