我有一个 yml 文件
spring:
datasource:
url: url
username:test
password: testpwd
api:
security:
username:foo
password: foopwd
我想在 Linux 计算机上使用命令行仅更新第一次出现的用户名和密码,如下所示:
spring:
datasource:
url: url
username:toto
password: totopsw
api:
security:
username:foo
password: foopwd
当我尝试时:
sed -i -e 's!^\(\s*username:\)[^"]*!\1toto!' test.yml
他更改了所有用户名
答案1
另一种sed
选择:
sed '1,/username/{/username/ s/:.*/:toto/};
1,/password/{/password/ s/:.*/:totopsw/}' infile
1,/regex/
从第一行开始到与给定匹配的第一行regex
(这里是username
字符串),更改“用户名”;对“密码”部分做同样的事情。
答案2
如果文件较长,这里有一个awk
基于 - 的解决方案,可以按行处理它:
awk '/^[[:space:]]+username/ && !u_chng{sub(/:.+$/,": toto"); u_chng=1}
/^[[:space:]]+password/ && !p_chng{sub(/:.+$/,": totospw"); p_chng=1} 1' input.yml
username
这将分别检查每一行是否以或开头password
。如果是这样,并且关联的标志u_chng
和p_chng
尚未设置,它将把 后面的值设置:
为您想要的新值,并设置相应的标志,以便忽略这些关键字的任何进一步出现。
结果:
spring:
datasource:
url: url
username: toto
password: totospw
api:
security:
username:foo
password: foopwd
请注意,如果您使用awk
不理解字符类 ( [[:space:]]
) 的实现,请更改
/^[[:space:]]+username/
到
/^[ \t]+username/
答案3
如果您的文件足够小,可以放入内存,您可以尝试将整个文件作为单个记录读取。这样,sed
只会在第一次看到“行”(记录)上的模式时进行替换:
$ sed -Ez 's/(username:)[^\n]*/\1toto/; s/(password:)[^\n]*/\1totopsw/' file.yaml
spring:
datasource:
url: url
username:toto
password:totopsw
api:
security:
username:foo
password: foopwd
要在原始文件中进行更改,只需添加-i
:
sed -i -Ez 's/(username:)[^\n]*/\1toto/; s/(password:)[^\n]*/\1totopsw/' file.yaml
答案4
如果bash
脚本有效,您可以使用以下sed
quit
命令:
#!/bin/bash
sed -E '
# If we find an username
/username/ {
# make the sobstitution of the username
s/^([[:space:]]*username:)/\1toto/g
n # Take the next line with the password
# Sobstitute the password
s/^([[:space:]]*password:).*$/\1totopw/g
q1 # Quit after the first match
}
' test.yml > new_test.yml
# How many line we have taken
len_line=$(sed -n '$=' new_test.yml)
# write the other line
sed "1,${len_line}d" test.yml >> new_test.yml
# rename all the file
rm -f test.yml
mv new_test.yml test.yml