Awk 如何使sed命令处理输入参数中非用户类型的转义字符?

Awk 如何使sed命令处理输入参数中非用户类型的转义字符?,awk,sed,Awk,Sed,我有一个文件,里面有一个密码占位符文本。我现在尝试查找占位符文本并用实际密码替换它。文本如下所示: USER_GIVEN_PASSWORD=<my_password> 我将输入传递到我的脚本,如下所示: sh password_replace.sh ABC&12345 我的预期产出是: USER_GIVEN_PASSWORD=ABC&12345 但我得到的结果如下: USER_GIVEN_PASSWORD=ABC<my_password>12345

我有一个文件,里面有一个密码占位符文本。我现在尝试查找占位符文本并用实际密码替换它。文本如下所示:

USER_GIVEN_PASSWORD=<my_password>
我将输入传递到我的脚本,如下所示:

sh password_replace.sh ABC&12345
我的预期产出是:

USER_GIVEN_PASSWORD=ABC&12345
但我得到的结果如下:

USER_GIVEN_PASSWORD=ABC<my_password>12345
但问题是我不应该调整输入参数来传递转义字符,因为密码不会手动输入。它将自动来自Azure密钥库之类的东西,作为我脚本的输入

因此,我需要让
sed
命令本身处理传入的特殊字符


有人能帮我做到这一点吗?

正如其他人所评论的,&是sed中的保留字,需要“转义”才能在替换文本中使用。另一种方法是使用awk(本例中为GNU awk):

awk-v pass=“$pass”-v confpass=“$confpass”-v schepass1=“$schepass1”-v schepass2=“$schpass2””/USER_gived_pass/{match($0,”);$0=substr($0,1,RSTART-1)pass=“$substr($0,RSTART+RLENGTH)}/确认用户_给定的密码/{match($0,”);$0=substr($0,1,RSTART-1)confpass($0,1,RSTART-1)schpass1“substr($0,RSTART+RLENGTH)}/SCHEMA2_密码/{match($0,”);$0=substr($0,1,RSTART-1)schpass2“substr($0,RSTART+RLENGTH)}1”文件
将密码作为变量“Pass”传递给awk。当遇到包含“USER_GIVEN_Pass”的行时,使用awk的匹配函数匹配“holder”的位置。将行($0)设置为等于字符串,直到placeholder,Pass,然后是字符串的其余部分

如果您有更高版本的GNU awk,您可以在满意后使用-i将更改提交回文件

否则:

awk -v pass="$pass" '/USER_GIVEN_PASS/ { match($0,"<my_password>");$0=substr($0,1,RSTART-1)pass""substr($0,RSTART+RLENGTH) }1' file > tmpfile && mv -f tmpfile file 
awk-v pass=“$pass””/USER\u给定的\u pass/{match($0)”;$0=substr($0,1,RSTART-1)pass“substr($0,RSTART+RLENGTH)}1”文件>tmpfile和&mv-f tmpfile文件

Sed不理解文字字符串,只理解regexp和支持反向引用的替换文本。请参阅,了解要使Sed表现为使用文字字符串时所需的长度

只需在awk中使用文字字符串函数即可:

$ new='ABC&12\345' awk '
    BEGIN { old="<my_password>"; lgth=length(old); new=ENVIRON["new"] }
    s = index($0,old) { $0 = substr($0,1,s-1) new substr($0,s+lgth) }
1' file
USER_GIVEN_PASSWORD=ABC&12\345
如果您使用的是GNU awk,您可以使用
-i-in-place
,就像您可以在使用GNU时使用
-i

new="$1" awk -i inplace 'script' file
或使用任何awk:

tmp=$(mktemp)
new="$1" awk 'script' file > "$tmp" && mv "$tmp" file

当awk命令在so
ENVIRON[]上启动时,
new=…
必须位于同一行的开头,这一点很重要
可以在不导出的情况下访问它。

&
在RHS中是一个完整的匹配反向引用,请将其转义。这是否回答了您的问题?另外,
&
不能作为shell中参数的一部分进行无引号传递,因为它是一个控制运算符。@Wiktor Stribizew:我认为当传递它。因为,正如问题中提到的,整个密码来自其他地方,它可能包含也可能不包含
&
或任何其他特殊字符。Aso,我对sed和regex非常陌生,您链接的问题已经超出了我的头脑:-(如果您的shell程序在变量中有密码,并且shell是Bash,那么您可以使用参数替换为
sed
pass=${pass/\/\\\\\};pass=${pass//&/\\\&}
。这很好,但只有当我有一个实例要替换时才有效。如果我在同一个文件中有多个这样的占位符呢?例如:
USER\u GIVEN\u PASSWORD=
CONFIRM\u USER\u GIVEN\u PASSWORD=SCHEMA1\u PASSWORD=相同的逻辑。传入更多变量,然后按照相同的过程进行ss.我修改了答案给你一个想法。这实际上只是将问题从
&
转移到
\
,而不是解决它,因为你仍然会得到一个需要转义的字符。顺便说一句,在字符串连接中使用
pass”“
pass
(末尾的空格)没有什么不同。
$ new='ABC&12\345' awk '
    BEGIN { old="<my_password>"; lgth=length(old); new=ENVIRON["new"] }
    s = index($0,old) { $0 = substr($0,1,s-1) new substr($0,s+lgth) }
1' file
USER_GIVEN_PASSWORD=ABC&12\345
new="$1" awk 'script' file
new="$1" awk -i inplace 'script' file
tmp=$(mktemp)
new="$1" awk 'script' file > "$tmp" && mv "$tmp" file