当我尝试按照以下方式进行检查时
sed -e 's,</Context>,<Resource name="ABC" password="'"$DB_PASS"'"/>\n&,' -i /path
sed正在截断反斜杠。
例如
DB_PASS='1!2@3#4$5%6^7&8*9(0)[{]}\|'
O / p是
<Resource name="jdbc/KARDB"
password=""1!2@3#4$5%6^7</Context>8*9(0)[{]}|""/> </Context>
如果我的DB_PASS
包含反斜杠,&amp ;,单引号双引号,我不希望sed更改密码内容。但要原样替换。
谢谢, 库苏马
答案 0 :(得分:0)
您遇到的具体问题是您的密码包含&
,s
命令的替换部分中的密码是指匹配的文本。
由于已成为我的一部分,因此将shell变量精确地替换为sed代码通常不是一个好主意,原因如下:sed无法区分代码和数据。这是可能出错的更无害的事情之一;想象一下如果某人输入了rm -Rf /,e #
这样的密码,GNU会怎么做。
使用GNU awk直接替换(因为RT
是GNU特定的,所以必须是gawk)
DB_PASS="$DB_PASS" gawk -v RS='</Context>' '{ printf $0; if(RT == RS) { print "<Resource name=\"jdbc/KARDB\" password=\"" ENVIRON["DB_PASS"] "\"/>" } printf RT }'
通常的-v dbpass="$DB_PASS"
技巧在这里不起作用,因为您甚至不希望解释转义序列,因此我们强制将DB_PASS
添加到awk
的环境并从那里获取。如果您希望文件在适当位置更改并且您具有GNU awk 4.1.0或更高版本,请将-i inplace
添加到awk的选项中,但我通常会使用cp file file~; awk ... file~ > file
进行备份,以防出现问题。< / p>
但是有一个问题:你如何处理密码中的"
?做dbpass = ENVIRON["DB_PASS"]; gsub(/"/, """, dbpass);
之类的事情并在输出中使用dbpass
可能是个好主意。对于所有其他关键字符也是如此,例如<
和>
。
由于您似乎正在解析XML数据,因此最好使用基于XML的工具,这样当Context
标记为空并写为{{1}时,您不会遇到问题并避免上述问题(可能是一个相当大的问题)。例如,使用xmlstarlet,您可以执行以下操作:
<Context/>
这包括三个步骤:
xmlstarlet ed -s '//Context' -t elem -n Resource -i '//Context/Resource[not(@name)]' -t attr -n name -v 'jdbc/KARDB' -i '//Context/Resource[@name="jdbc/KARDB"]' -t attr -n password -v "$DB_PASS"
在每个-s '//Context' -t elem -n Resource
节点下插入一个空的Resource
子节点(如果只有一个节点,则可以这样做;否则您可能希望更详细地指定它)
Context
在每个没有名称的-i '//Context/Resource[not(@name)]' -t attr -n name -v 'jdbc/KARDB'
节点中插入一个属性name="jdbc/KARDB"
(希望只有我们刚刚插入的那个),并且
Context/Resource
在-i '//Context/Resource[@name="jdbc/KARDB"]' -t attr -n password -v "$DB_PASS"
属性password
节点下的每个$DB_PASS
节点中插入值Resource
(正确引用)的Context
属性name
(同样,这应该只是我们刚插入的节点)。对于一次性插入整个节点的更完美的解决方案,您需要仔细研究xslt,但如果您对原始的sed方法感到满意,那么这种方法的缺点都不应该是一个问题。 / p>