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

时间:2013-04-08 17:47:41

标签: 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,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=-1anongid=-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)

从示例中可以看出,anonuidanongid可能已存在于括号内,但原始括号列表可能有一个字符串而不是另一个字符串(第2行, 3和4),列表既没有(第1行),列表已经正确设置(第5行),或者甚至其中一个或两个都设置不正确(第3行)。如果anonuidanongid设置为-1以外的值,则必须将其更改为-1的正确值(第3行)。

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

3 个答案:

答案 0 :(得分:2)

我认为这可以满足您的需求:

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,每个部分都有一些逻辑来决定是否需要替换或添加适当的值。 (它无需检查值是否已经正确,这会使事情变得复杂而不改变结果。)

答案 1 :(得分:1)

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

$ sed '/anonuid=..*,anongid=..*)$/!p' $file

上面将打印(p)所有与两个斜杠之间的正则表达式不匹配的行。我使用! 否定 表达式。这样,您就不会在其中与anaonuidanongid匹配。

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

$ sed '/anonuid=..*,anongid=..*)$/!s/from/to/`

操作可能相当复杂,您可能会传递多个sed命令以使所有恰到好处

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

$ sed 's/no_root_squash.*$/no_root_squash,anonuid=-1,anongid=-1)/' $file

这是在查找no_root_squash字符串,并将所有内容从该字符串替换为所需文本的行尾。您接触的线条是否需要编辑?是的,但你并没有真正改变这些界限。您基本上用/no_root_squash,anonuid=-1,anongid=-1)代替/no_root_squash,anonuid=-1,anongid=-1)

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

响应

  

谢谢大卫!是的,我正在考虑走那条路,但我不想100%依赖包含no_root_squash的每一行。我当前的配置文件只以该字符串结尾,但我不是100%肯定在该字段中可能不会有所不同。你认为有没有办法改变它,所以它只是从不包含anonuid = -1或anongid = -1的最后一个字符串的末尾覆盖?

你能保证在每一行中有什么保证?

您可以执行捕获组:

 sed 's/\(sync,[^,)]*\).*/\1,anonuid=-1,anongid=-1)/' $file

\(..\)捕获组。它基本上捕获匹配正则表达式的那一部分,然后允许您通过\1重用它。我从单词sync捕获到一组不包括逗号或右括号的字符。然后,我附加了捕获组,一个逗号,以及你的anid uid和gid。

这会起作用吗?

答案 2 :(得分:0)

也许我过于简单化了:

sed 's/anonuid=[-0-9]*[^)]//g;s/anongid=[-0-9]*[^)]//g;s/[)]/anonuid=-1,anongid=-1)/g' test.txt > test3.txt

这会删除anonuidanongid的所有当前实例并添加字符串 "anonuid=-1,anongid=-1"加入括号