sed:如何删除包含斜杠的模式匹配行?

26

假设文件 /etc/fstab 包含以下内容:

/dev/xvda1 / ext4 defaults 1 1
/dev/md0    /mnt/ibsraid    xfs defaults,noatime    0   2
/mnt/ibsraid/varlog /var/log    none    bind    0   0
/dev/xvdb   None    auto    defaults,nobootwait 0   2

我想要删除以/dev/xvdb开头的那行内容。因此我尝试了以下命令:

$ sed '/^/dev/xvdb/d' /etc/fstab
sed: -e expression #1, char 5: extra characters after command
$ sed '?^/dev/xvdb?d' /etc/fstab
sed: -e expression #1, char 1: unknown command: `?'
$ sed '|^/dev/xvdb|d' /etc/fstab
sed: -e expression #1, char 1: unknown command: `|'

这些都没有起作用。我尝试将定界符更改为?|,因为当模式包含/时,使用sed替换命令可以起到作用。

我正在Debian上使用GNU Sed 4.2.1。


Stack Overflow是一个关于编程和开发问题的网站。这个问题似乎不属于编程或开发范畴。请参阅帮助中心中的我可以在这里问什么样的问题。也许超级用户Unix&Linux Stack Exchange更适合提问。 - jww
3个回答

49
你离正确很近了。当你使用一个非标准的字符作为模式分隔符,比如|pattern|,第一次使用该字符时必须进行转义。
$ sed '\|^/dev/xvdb|d' /etc/fstab
/dev/xvda1 / ext4 defaults 1 1
/dev/md0    /mnt/ibsraid    xfs defaults,noatime    0   2
/mnt/ibsraid/varlog /var/log    none    bind    0   0

同样地,可以使用以下代码:
sed '\?^/dev/xvdb?d' /etc/fstab

最后,如果以你的回答中所示的方式进行转义,可以在/pattern/内部使用斜杆。

1
+1:不错,我记得在某个地方读过模式分隔符的内容,但是已经忘记了。谢谢你的提醒。 - jaypal singh
@John1024 有没有办法我们可以在 awk 中使用相同的方法, 我的模式包含 '/':我是这样使用它的:awk "/PATTERN/{flag=1;next} /PATTERN2|PATTERN3/{flag=0} flag" filename即打印从 pat1 到 pat2 或 pat3 之间的所有内容(不包括模式)。 - Prabhat Kumar Singh
@PrabhatKumarSingh 当使用awk时,如果您的模式包含/,则必须使用反斜杠进行转义,例如\/。因此,在awk中匹配/dev/xvdb的模式应写为/\/dev\/xvdb/' - John1024
我们如何将变量用作模式。例如:path=/dev/xvdb。sed '\|^$path|d' /etc/fstab 对我不起作用。 - Saurav Sahu
@SauravSahu 使用双引号而不是单引号。这样就可以工作了。 - Prabhat Kumar Singh
1
@John1024 是的,那样做可以,但是值不是静态的,所以将其存储在变量中,并从那里使用。 awk -v var=$path '...' - Prabhat Kumar Singh

5
经过一番搜索,我发现使用\可以在模式字符串中转义/。所以这个方法可行:
$ sed '/^\/dev\/xvdb/d' /etc/fstab

0
为什么执着于使用斜杠作为你的分隔符呢?可以尝试使用其他字符,比如逗号:
sed ',^/dev/xvdb,d' /etc/fstab

或者一个冒号:

sed ':^/dev/xvdb:d' /etc/fstab

或者任何使其易于阅读的方式。分隔符可以是任何字符。惯例是使用正斜杠,但当它变得笨拙时,切换到其他字符。

请注意,如果您想要更改文件本身而不是输出结果,则需要使用“原地”标志-i

sed -i ':^/dev/xvdb:d' /etc/fstab

2
你使用的是哪个版本的 sed?根据 GNU sed 手册第 3.2 节 的说明,如果你在地址中使用了一个不同于 / 的分隔符,则必须对其进行转义。(请注意,这仅适用于地址指定符,而不适用于 s 命令。) - John1024
3
如果您读了我的问题,我尝试了不同的分隔符,并发现这并没有起作用。 - donatello

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接