Bash 使用sed修改不包含字符串的行

Bash 使用sed修改不包含字符串的行,bash,Bash,我正在尝试编写一个bash脚本,它使用sed修改配置文件中不包含特定字符串的行。为了举例说明,我可以 /some/file/path1 ipAddress1/subnetMask(rw,sync,no_root_squash) /some/file/path2 ipAddress1/subnetMask(rw,sync,no_root_squash,anonuid=-1) /some/file/path3 ipAddress2/subnetMask(rw,sync,no_root_squash,

我正在尝试编写一个bash脚本,它使用sed修改配置文件中不包含特定字符串的行。为了举例说明,我可以

/some/file/path1 ipAddress1/subnetMask(rw,sync,no_root_squash)
/some/file/path2 ipAddress1/subnetMask(rw,sync,no_root_squash,anonuid=-1)
/some/file/path3 ipAddress2/subnetMask(rw,sync,no_root_squash,anonuid=0)
/some/file/path4 ipAddress2/subnetMask(rw,sync,no_root_squash,anongid=-1)
/some/file/path5 ipAddress2/subnetMask(rw,sync,no_root_squash,anonuid=-1,anongid=-1)
我想更改每一行的插入列表,使其包含括号内的字符串
anonuid=-1
anongid=-1

/some/file/path1 ipAddress1/subnetMask(rw,sync,no_root_squash,anonuid=-1,anongid=-1)
/some/file/path2 ipAddress1/subnetMask(rw,sync,no_root_squash,anonuid=-1,anongid=-1)
/some/file/path3 ipAddress2/subnetMask(rw,sync,no_root_squash,anonuid=-1,anongid=-1)
/some/file/path4 ipAddress2/subnetMask(rw,sync,no_root_squash,anongid=-1,anonuid=-1)
/some/file/path5 ipAddress2/subnetMask(rw,sync,no_root_squash,anonuid=-1,anongid=-1)
从示例中可以看出,
anonuid
anongid
可能已经存在于括号内,但原始括号列表可能有一个字符串,但没有另一个(第2、3和4行),列表没有(第1行),列表已经正确设置(第5行),甚至其中一个或两个设置不正确(第3行)。当
anonuid
anongid
设置为
-1
以外的值时,必须将其更改为
-1
的正确值(第3行)


使用sed编辑我的配置文件的最佳方法是什么,这样
anonuid=-1
anongid=-1
包含在每行的附加列表中,当然用逗号分隔符分隔?

我想这就是您想要的:

sed -e '/anonuid/{s/anonuid=[-0-9]*/anonuid=-1/;b gid;};s/)$/,anonuid=-1)/;:gid;/anongid/{s/anongid=[-0-9]*/anongid=-1/;b;};s/)$/,anongid=-1)/'

基本上,它有两个几乎相同的部分,第一个处理anonuid,第二个处理anongid,每个部分都有一点逻辑来决定是否需要替换或添加适当的值。(不必费心检查值是否已经正确,这只会使事情复杂化,而不会改变结果。)

我认为这正是您想要的:

sed -e '/anonuid/{s/anonuid=[-0-9]*/anonuid=-1/;b gid;};s/)$/,anonuid=-1)/;:gid;/anongid/{s/anongid=[-0-9]*/anongid=-1/;b;};s/)$/,anongid=-1)/'

基本上,它有两个几乎相同的部分,第一个处理anonuid,第二个处理anongid,每个部分都有一点逻辑来决定是否需要替换或添加适当的值。(不必检查值是否已经正确,这只会在不更改结果的情况下使事情复杂化。)

您可以使用sed指定感兴趣的行:

$ sed '/anonuid=..*,anongid=..*)$/!p' $file
上面将打印(
p
)两个斜杠之间与正则表达式不匹配的所有行。我用
否定了表达式。这样,您就不会同时使用
anaonuid
anongid
匹配行

现在,您可以使用sed
s
命令处理不匹配的行并编辑这些行:

$ sed '/anonuid=..*,anongid=..*)$/!s/from/to/`
操作可能相当复杂,您可能要传递多个
sed
命令以使一切正常

但是,如果字符串
no\u root\u squash
出现在您要更改的每一行中,为什么不采取简单的方法:

$ sed 's/no_root_squash.*$/no_root_squash,anonuid=-1,anongid=-1)/' $file
这是寻找
no\u root\u squash
字符串,并用所需的文本替换从该字符串到行尾的所有内容。是否有您正在触摸的线不需要编辑?是的,但你并没有真正改变那些台词。您基本上是用相同的
/no\u root\u squash,anonuid=-1,anongid=-1)
替换
/no\u root\u squash,anonuid=-1,anongid=-1)

这可能会更快,即使它正在替换不需要替换的文本,因为正在进行的处理更少。另外,将来更容易理解和支持

回应
谢谢你,大卫!是的,我正在考虑走那条路线,但我不想100%依赖每一条不含南瓜的路线。我当前的配置文件仅以该字符串结尾,但我不能100%确定该字段中是否存在潜在的差异。您认为有没有一种方法可以改变这一点,使它只覆盖最后一个不包含anonuid=-1或anongid=-1的字符串的末尾

你能保证每一行都有什么

您可能可以创建一个捕获组:

 sed 's/\(sync,[^,)]*\).*/\1,anonuid=-1,anongid=-1)/' $file
\(..\)
是一个捕获组。它基本上捕获匹配正则表达式的该部分,然后允许您通过
\1
重用它。我从单词
sync
捕获到一组字符,不包括逗号或右括号。然后,我将添加捕获组、一个逗号以及您的anon uid和gid


这行吗?

您可以使用sed指定感兴趣的行:

$ sed '/anonuid=..*,anongid=..*)$/!p' $file
上面将打印(
p
)两个斜杠之间与正则表达式不匹配的所有行。我用
否定了表达式。这样,您就不会同时使用
anaonuid
anongid
匹配行

现在,您可以使用sed
s
命令处理不匹配的行并编辑这些行:

$ sed '/anonuid=..*,anongid=..*)$/!s/from/to/`
操作可能相当复杂,您可能要传递多个
sed
命令以使一切正常

但是,如果字符串
no\u root\u squash
出现在您要更改的每一行中,为什么不采取简单的方法:

$ sed 's/no_root_squash.*$/no_root_squash,anonuid=-1,anongid=-1)/' $file
这是寻找
no\u root\u squash
字符串,并用所需的文本替换从该字符串到行尾的所有内容。是否有您正在触摸的线不需要编辑?是的,但你并没有真正改变那些台词。您基本上是用相同的
/no\u root\u squash,anonuid=-1,anongid=-1)
替换
/no\u root\u squash,anonuid=-1,anongid=-1)

这可能会更快,即使它正在替换不需要替换的文本,因为正在进行的处理更少。另外,将来更容易理解和支持

回应
谢谢你,大卫!是的,我正在考虑走那条路线,但我不想100%依赖每一条不含南瓜的路线。我当前的配置文件仅以该字符串结尾,但我不能100%确定该字段中是否存在潜在的差异。您认为有没有一种方法可以改变这一点,使它只覆盖最后一个不包含anonuid=-1或anongid=-1的字符串的末尾

你能保证每一行都有什么

你也许可以做一个捕获g