linux sed在与变量匹配后替换第3行

vx6bjr1n  于 11个月前  发布在  Linux
关注(0)|答案(4)|浏览(124)

我有一个这样的文件:

[profile.one]
username=sam
password=secret
email=something

[profile.two]
username=kate
password=secret
email=something

[profile.three]
username=mary
password=secret
email=something

字符串
我想创建一个shell脚本来更改[profile.two]中的密码。新密码将是一个变量(由另一个shell脚本触发。例如,新密码将显示为$1
我知道我应该使用sed,但在那之后,我一直在努力解决语法问题。

deyfvvtc

deyfvvtc1#

一个简单的实现是从起始行搜索到替换行,然后在该范围内搜索并替换替换行。

sed '/^\[profile\.two\]/,/password=/{
    s/password=.*/password='"$1/;}" file

字符串
一旦像您希望的那样工作,您可以添加-i选项将更改写回文件,而不是标准输出。
这本身就是脆弱的,因为$1不能包含在这种上下文中对sed有意义的字符-特别是换行符或斜杠。
这会显式地查找password=,而不是希望它正好位于节标题之后的第三行。

e7arh2l6

e7arh2l62#

sed -i "/\[profile\.two]/{n;n;s/secret/$1/}" fileName

字符串
注意:[和.字符需要转义以匹配文字
x1c 0d1x的数据



注意事项:两个$1的含义是不一样的。changePasswd函数中的$1接收传递给函数的第一个参数; changePasswd调用中的$1接收传递给脚本的第一个参数。
测试结果:


t8e9dugd

t8e9dugd3#

awk通常比sed更擅长这类事情。

$ foo() {
    awk '
    $1 == "[profile.two]" {gsub("\npassword=[^\n]*", "\npassword=" new_password)}1
    ' new_password=$1 RS= ORS='\n\n' input; }
$ foo banana
[profile.one]
username=sam
password=secret
email=something

[profile.two]
username=kate
password=banana
email=something

[profile.three]
username=mary
password=secret
email=something

字符串
在这里,我创建函数foo的唯一目的是将密码输入到$1中。使用命名变量会更干净,这只是一个廉价的文学技巧,用于展示如何在脚本中使用该命令。
awk有一个很好的特性,允许你在空白行上分隔记录,这是通过将RS设置为空字符串来完成的。(这里,$1不是函数的参数,而是直接传递给awkawk使用它来选择记录中的第一个字段),然后仅对该记录执行替换。
如果你知道密码总是在记录的第3行(把标题算作一行),你可以简化一点,只需要做:

awk '$1 == "[profile.two]" {$3="password=" new_password}1
        ' new_password=$1 RS= ORS='\n\n' OFS='\n' input


在上述所有内容中,我假设您的数据位于名为input的文件中。

klh5stk1

klh5stk14#

这可能对你有用(GNU sed):

v="s}[r3t"
<<<"password=$v" sed -e '/^\[profile\.two\]/,/^$/{/password/{r /dev/stdin' -e 'd}}' file

字符串
v中设置密码。
将密码复制为一行文件,并使用here-string将其提供给sed调用。
在sed调用中,搜索以[profile.two]开始并以空行(或文件结尾)结束的范围。
在上述范围内,匹配一行password,并将其替换为here-document提供的行,然后删除当前行。
注意:密码将包含并且应该包含特殊字符,例如$*&[]等,因此为了避免这些字符与sed本身混淆,将密码作为单独文件中的一行传递。在本例中,是一个here-document。

相关问题