Regex 使用sed否定部分模式

Regex 使用sed否定部分模式,regex,bash,sed,regex-negation,regex-group,Regex,Bash,Sed,Regex Negation,Regex Group,我想创建一个模式,该模式将查找与该模式匹配的第一个字符串并替换它: sed -r '0,/^[a-z0-9]* (ALL=\(ALL\) ALL)/s//abc \1\n&/' 我的输入是一个/etc/sudoers文件 我想将^[a-z0-9]*更改为类似/^ALL/但它对我不起作用。我猜您希望从字符串中删除abc,此表达式可能有助于您这样做: ([^abc]*)(.*) 正则表达式 如果这不是您想要的表达式,您可以在中修改/更改表达式 正则表达式电路 您还可以在以下位置可视化您

我想创建一个模式,该模式将查找与该模式匹配的第一个字符串并替换它:

sed -r '0,/^[a-z0-9]* (ALL=\(ALL\) ALL)/s//abc \1\n&/'
我的输入是一个
/etc/sudoers
文件


我想将
^[a-z0-9]*
更改为类似
/^ALL/
但它对我不起作用。

我猜您希望从字符串中删除
abc
,此表达式可能有助于您这样做:

([^abc]*)(.*)

正则表达式 如果这不是您想要的表达式,您可以在中修改/更改表达式

正则表达式电路 您还可以在以下位置可视化您的表达式:


替换文件中的第一个匹配项

如果我理解您的问题,并且您希望在文件中找到与
^[a-z0-9]+ALL=(ALL)ALL
匹配的第一个字符串,并使用扩展正则表达式将
^[a-z0-9]+ALL
替换为类似
^ABC
,您可以使用:

sed -r '0,/[a-z0-9]+/s/^[a-z0-9]+ ALL(=\(ALL\) ALL.*$)/^ABC\1/'
查看
/etc/sudoers
中为
wheel
组的成员提供了
sudo
访问权限的未注释行,您将有:

$ noc /etc/sudoers
root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL
因此,要将
/etc/sudoers
中的第一个字符串替换为
[a-z0-9]+ALL=(ALL)ALL
,您需要:

$ noc /etc/sudoers | sed -r '0,/[a-z0-9]+/s/^[a-z0-9]+ ALL(=\(ALL\) ALL.*$)/^ABC\1/'
^ABC=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL
按评论编辑

在你的评论中,你说你想找到“
ALL=(ALL)ALL
,其中
string
可以是一切,但不能是
'ALL'
”。由于
sed
不支持“向前看”或“四处看”,因此最好不要在行首显式地匹配
ALL
。这意味着您要查找以
^[^A][^L][^L]
开头的行。虽然这在某种程度上是有限制的,但它将查找不以
开头的行“ALL”
,这可能是您唯一的求助方式。比如:

sed -r '0,/^[^A][^L][^L]/s/^[^A][^L][^L][^ ]+( ALL=\(ALL\) ALL.*$)/^ABC\1/'
再次以
sudoers
文件为例,包括您不想匹配的
ALL=(ALL)ALL
,例如

$ cat sudoers
ALL ALL=(ALL) ALL
root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL
现在在
ALL=(ALL)ALL
中应用表达式定位第一个
而不是
ALL
,您将得到:

$ sed -r '0,/^[^A][^L][^L]/s/^[^A][^L][^L][^ ]+( ALL=\(ALL\) ALL.*$)/^ABC\1/' sudoers
ALL ALL=(ALL) ALL
^ABC ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL

替换行中编号的出现项

如果要替换行中的引用。对于扩展正则表达式,使用
s/find/replace/n
,其中
n=1,2,3..
是要替换的
find
模式的引用,您可以将第一个引用替换为,例如

sed -r 's/[0-9a-z]+/cde456/1'
例如:

$ echo "abc123---abc123---abc123" | sed -r 's/[0-9a-z]+/cde456/1'
cde456---abc123---abc123
或者,要替换第二个引用,可以使用:

$ echo "abc123---abc123---abc123" | sed -r 's/[0-9a-z]+/cde456/2'
abc123---cde456---abc123
基本正则表达式也有相同的匹配项,您只是没有可用的
“+”
(匹配一个或多个匹配项),是否必须更改
查找模式,例如

sed 's/[0-9a-z][0-9a-z]*/cde456/1`

如果
ALL
出现在
ALL=(ALL)ALL
子字符串之前的部分中,则我理解您希望避免匹配模式的第一个匹配项

使用

如果您没有GNU
sed
您可以尝试

sed -i '' -e '/^.*ALL.* ALL=(ALL) ALL/b' -e 's/^.* \(ALL=(ALL) ALL\)/abc \1\n&/' -e ':a;n;ba' file
注释

  • /^.*ALL.*ALL=(ALL)ALL/b
    -查找在
    ALL=(ALL)ALL
    之前包含
    ALL
    的行,并停止处理该行
  • s/^.*\(ALL=(ALL)ALL\)/abc\1\n&/
    执行替换(注意
    *
    将尽可能多地匹配任何0个或更多字符)
  • T
    -如果不成功,则结束对该行的处理
  • :a;Nba
    -一个循环,使sed只需读取并打印文件末尾的其余行

不,我想让正则表达式匹配
ALL=(ALL)ALL
where string可以是一切,但不是'ALL'。我想让正则表达式匹配ALL=(ALL)ALL,where string可以是一切,但不是'ALL'。如果您仍在忙,请澄清:是否要跳过(避免匹配)
abcALL ALL=(ALL)全部
abc全部=(全部)全部…全部…
?或者两者都有?
sed 's/[0-9a-z][0-9a-z]*/cde456/1`
sed -i '/^.*ALL.* ALL=(ALL) ALL/b;s/^.* \(ALL=(ALL) ALL\)/abc \1\n&/;T;:a;n;ba' file
sed -i '' -e '/^.*ALL.* ALL=(ALL) ALL/b' -e 's/^.* \(ALL=(ALL) ALL\)/abc \1\n&/' -e ':a;n;ba' file