我有一个包含多行的文件。我正在尝试获取出现在特定模式之后的字符串......
这是我正在尝试执行的命令:
sed -n -e 's/^.*DB_PASS=//p' <<< $(cat /root/dadosDB)
但它不是只给我想要的行,而是给我指定模式之后的所有内容......
我的期望:
仅返回包含该行的输出DB_PASS
并忽略其他行。
该命令正在做什么:
在该模式之后打印整个文件的所有内容DB_PASS
,并忽略该模式之前出现的所有内容。
任何帮助表示赞赏!
这是我里面的内容dadosDB
:
DB_USER=myusername
DB_PASS=mypassword
DB_NAME=mydatabase
我只想获取后面的内容DB_PASS=
并停在该行,忽略后面的内容。
实际输出sed
:
$ sed -n 's/^.*DB_PASS=//p' <<< $(cat /root/dadosDB)
mypassword DB_NAME=mydatabase
我需要的:
mypassword
答案1
得到此结果的原因是因为您没有将命令sed
直接应用于文件,而是应用到命令替换的结果。
这意味着文本处理实际上并未应用于
DB_USER=myusername
DB_PASS=mypassword
DB_NAME=mydatabase
cat
而是在压缩行的不带引号的命令替换之后应用于文件内容的命令的结果。
如果你试试
echo $(cat /root/dadosDB)
你会注意到输出是
DB_USER=myusername DB_PASS=mypassword DB_NAME=mydatabase
全部在一行上,而不是在单独的行上。如果将命令替换放在双引号中,如
echo "$(cat /root/datosDB)"
换行符将被保留。
关键点是
- 您既不需要
cat
也不需要命令替换,并且 - 如果您使用命令替换而不将其放在双引号中,您将丢失换行符(请参阅这个问答例如)。(1)
长话短说:
使用
sed -n -e 's/^.*DB_PASS=//p' /root/dadosDB
更确切地说)
sed -n -e 's/^DB_PASS=//p' /root/dadosDB
排除具有不同开头的关键字的行,但是结尾在DB_PASS
。
请注意:你写的“并停在那一行,忽略下面的行。”我认为这意味着你想要打印之后的词DB_PASS
,但不是以下行(从技术上讲,它们也出现在 后面DB_PASS
。如果您的意思是可能有更多行以 开头DB_PASS
,并且您想确保仅匹配第一行,则需要稍作调整:
sed -n -e '0,/DB_PASS/s/^DB_PASS=//p' /root/dadosDB
(1)请注意,您的特定情况下的问题是您的 shell(我假设是 Bash)如何处理带有不带引号的替换的“Here-strings”,因此(如 @steeldriver 所指出的)更好的演示是
cat <<< "$(cat /root/dadosDB)"
与
cat <<< $(cat /root/dadosDB)
该行为有Bash v4.4 进行了更改:之前,这两个命令的输出与上面提到的示例相同echo
。在 Bash 的更高版本中,不带引号的命令替换将不再导致分词和随后的多行输出压缩。
如果您有兴趣了解更多信息,您可能想看看
另外,我建议你使用以下方法检查你的脚本shellcheck
,也可在许多 Linux 发行版上作为独立工具使用,以避免语法(和其他)错误。
答案2
您还可以使用,(对我来说)这似乎是比该任务awk
更适合的选项:sed
$ awk -F'=' '$1 == "DB_PASS" { print $2 }' /root/dadosDB
mypassword
grep
另一种选择是和的组合cut
:
$ grep "^DB_PASS=" /root/dadosDB | cut -d= -f2
mypassword
请注意,这两个命令都将输入视为列相隔=
.
答案3
尝试这个:
sed -n "s/.*DB_PASS=\(.*\)/\1/p" <<< $(cat /root/dadosDB)
如果只有一行 ->
echo "DB_USER=myusername DB_PASS=mypassword DB_NAME=mydatabase" | sed -n "s/.*DB_PASS=\(.*\)DB.*/\1/p"