我想创建一个模式,该模式将找到与该模式匹配的第一个字符串并将其替换:
sed -r '0,/^[a-z0-9]* (ALL=\(ALL\) ALL)/s//abc \1\n&/'
我的输入是一个/etc/sudoers
文件。
我想将^[a-z0-9]*
更改为/^ALL/!
之类的内容,但对我来说不起作用。
答案 0 :(得分:1)
我的猜测是您想从字符串中删除abc
,此表达式可能会帮助您这样做:
([^abc]*)(.*)
#!/bin/bash
STRING="(ALL=(ALL) ALL)/s//abc"
MATCH="$(sed 's/\([^abc]*\)\(.*\)/\1/' <<< $STRING)"
echo $MATCH
(ALL=(ALL) ALL)/s//
如果这不是您想要的表达式,则可以在regex101.com中修改/更改表达式。
您还可以在jex.im中可视化您的表达式:
答案 1 :(得分:1)
替换文件中的首次出现
如果我理解您的问题,并且您想在文件中找到与^[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
组成员具有sudo
访问权限的wheel
中未注释的行,您将:
$ noc /etc/sudoers
root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL
因此,将[a-z0-9]+ ALL=(ALL) ALL
中的第一个字符串替换为/etc/sudoers
中的^ABC=(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
按评论编辑
在评论中,您说要查找“ <string> 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) ALL
,例如
$ cat sudoers
ALL ALL=(ALL) ALL
root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL
现在应用表达式来定位<string>
中第一个ALL
而不是<string> 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
基本正则表达式可以使用相同的匹配项,只是您没有'+'
(匹配一个或多个匹配项),是否必须更改find
模式,例如
sed 's/[0-9a-z][0-9a-z]*/cde456/1`
在不使用扩展正则表达式的情况下替换所需的出现。
答案 2 :(得分:0)
我了解,如果ALL
子字符串之前的部分中有ALL=(ALL) ALL
,则您要避免匹配模式的第一次出现。
使用
sed -i '/^.*ALL.* ALL=(ALL) ALL/b;s/^.* \(ALL=(ALL) ALL\)/abc \1\n&/;T;:a;n;ba' file
如果您没有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;n;ba
-使sed只需读取并打印其余行到文件末尾的循环。