正确的字符串转义策略
Proper escape strategy for strings
我正在编写一个简单的 BASH 脚本来生成一个 LDIF 文件,然后我可以使用该文件将用户添加到我的 OpenLDAP 服务器。
这是脚本:
#!/bin/bash
#add LDAP user, v1.0, by mbobak, 11/17/2020
if [ $# != 6 ];
then
echo "`basename [=10=]`: error: invalid number of arguments:"
echo "`basename [=10=]` <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>"
exit 1
fi
userid=
firstname=
lastname=
gidnum=
uidnum=
empno=
temppasswd=`slappasswd -s pw4${userid}`
echo ${userid} ${firstname} ${lastname} ${gidnum} ${uidnum} ${empno} ${temppasswd}
sed -e "s/#userid#/${userid}/g" -e "s/#gidnum#/${gidnum}/g" -e "s/#firstname#/${firstname}/g" -e "s/#lastname#/${lastname}/g" -e "s/#uidnum#/${uidnum}/g" -e "s/#empno#/${empno}/g" -e "s/#temppasswd#/${temppasswd}/g" user_tmpl.ldif
我将它与此模板一起使用:
dn: uid=#userid#,ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: #userid#
gidNumber: #gidnum#
givenName: #firstname#
sn: #lastname#
displayName: #firstname# #lastname#
homeDirectory: /home/#userid#
mail: #userid#@nitssolutions.com
loginShell: /bin/bash
cn: #firstname# #lastname#
uidNumber: #uidnum#
employeeType: INT-FT
employeeNumber: #empno#
dn: uid=#userid#,ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: #temppasswd#
这似乎工作得很好,除了 当 slappasswd
的输出包含 /
字符时。
发生这种情况时,我收到以下错误:
./add_ldap_user.sh jdoe John Doe 123456 123456 NS1234
jdoe John Doe 123456 123456 NS1234 {SSHA}kTwHVDBiK4ub3laqwaqZpAUwILrW/Vw9
sed: -e expression #7, char 51: unknown option to `s'
同样,只有当 slappasswd
的输出包含 /
.
时才会发生这种情况
我确定我在这里遗漏了一些简单的东西,但我不清楚正确答案是什么。我不能简单地转义整个表达式,否则我的变量将恢复为静态字符串“${temppasswd}”,这无济于事。我需要 ${temppasswd} 的值,即使它包含需要转义的字符。
帮忙?
this only happens when the output of slappasswd contains a /.
选择不同的 s
命令分隔符。像 ~
或任何其他字符。
sed -e "s~#userid#~${userid}~g"
在 GNU sed 的边缘情况下,您可以使用 any 字节,例如,您可以使用 C 转义 $'\x01'
来写入 0x01 字节:
sed -e $'s\x01#userid#\x01'"${userid}"$'\x01g'
但我建议不要重新发明轮子并使用现有的模板工具。将模板格式从 #userid#
更改为 ${userid}
,您可以使用 envsubst
.
使用 envsubst
和以下重新设计的模板:
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: ${userid}
gidNumber: ${gidnum}
givenName: ${firstname}
sn: ${lastname}
displayName: ${firstname} ${lastname}
homeDirectory: /home/${userid}
mail: ${userid}@nitssolutions.com
loginShell: /bin/bash
cn: ${firstname} ${lastname}
uidNumber: ${uidnum}
employeeType: INT-FT
employeeNumber: ${empno}
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: ${temppasswd}
已处理:program1
#!/usr/bin/env bash
Iam="${0##*/}" # Basename of myself
if [ $# -ne 6 ];
cat <<ERR >&2
$Iam: error: invalid number of arguments:
Usage:
$Iam <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>
ERR
exit 1
fi
userid="" firstname="" lastname="" \
gidnum="" uidnum="" empno="" \
temppasswd=$(slappasswd -s "pw4$userid") \
envsubst <user_tmpl.ldif
使用虚拟值测试 运行:
./program1 foo bar baz 666 42 99
foo bar baz 666 42 99 ciWatEpIcs
输出
dn: uid=foo,ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: foo
gidNumber: 666
givenName: bar
sn: baz
displayName: bar baz
homeDirectory: /home/foo
mail: foo@nitssolutions.com
loginShell: /bin/bash
cn: bar baz
uidNumber: 42
employeeType: INT-FT
employeeNumber: 99
dn: uid=foo,ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: ciWatEpIcs
现在有了一个简单的here文档,它甚至不需要envsubst
program2
:
#!/usr/bin/env bash
Iam="${0##*/}" # Basename of myself
if [ $# -ne 6 ];
then
cat <<ERR >&2
$Iam: error: invalid number of arguments:
Usage:
$Iam <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>
ERR
exit 1
fi
userid=
firstname=
lastname=
gidnum=
uidnum=
empno=
temppasswd=$(slappasswd -s "pw4$userid")
cat <<LDIFTEMPLATE
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: ${userid}
gidNumber: ${gidnum}
givenName: ${firstname}
sn: ${lastname}
displayName: ${firstname} ${lastname}
homeDirectory: /home/${userid}
mail: ${userid}@nitssolutions.com
loginShell: /bin/bash
cn: ${firstname} ${lastname}
uidNumber: ${uidnum}
employeeType: INT-FT
employeeNumber: ${empno}
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: ${temppasswd}
LDIFTEMPLATE
我正在编写一个简单的 BASH 脚本来生成一个 LDIF 文件,然后我可以使用该文件将用户添加到我的 OpenLDAP 服务器。
这是脚本:
#!/bin/bash
#add LDAP user, v1.0, by mbobak, 11/17/2020
if [ $# != 6 ];
then
echo "`basename [=10=]`: error: invalid number of arguments:"
echo "`basename [=10=]` <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>"
exit 1
fi
userid=
firstname=
lastname=
gidnum=
uidnum=
empno=
temppasswd=`slappasswd -s pw4${userid}`
echo ${userid} ${firstname} ${lastname} ${gidnum} ${uidnum} ${empno} ${temppasswd}
sed -e "s/#userid#/${userid}/g" -e "s/#gidnum#/${gidnum}/g" -e "s/#firstname#/${firstname}/g" -e "s/#lastname#/${lastname}/g" -e "s/#uidnum#/${uidnum}/g" -e "s/#empno#/${empno}/g" -e "s/#temppasswd#/${temppasswd}/g" user_tmpl.ldif
我将它与此模板一起使用:
dn: uid=#userid#,ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: #userid#
gidNumber: #gidnum#
givenName: #firstname#
sn: #lastname#
displayName: #firstname# #lastname#
homeDirectory: /home/#userid#
mail: #userid#@nitssolutions.com
loginShell: /bin/bash
cn: #firstname# #lastname#
uidNumber: #uidnum#
employeeType: INT-FT
employeeNumber: #empno#
dn: uid=#userid#,ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: #temppasswd#
这似乎工作得很好,除了 当 slappasswd
的输出包含 /
字符时。
发生这种情况时,我收到以下错误:
./add_ldap_user.sh jdoe John Doe 123456 123456 NS1234
jdoe John Doe 123456 123456 NS1234 {SSHA}kTwHVDBiK4ub3laqwaqZpAUwILrW/Vw9
sed: -e expression #7, char 51: unknown option to `s'
同样,只有当 slappasswd
的输出包含 /
.
我确定我在这里遗漏了一些简单的东西,但我不清楚正确答案是什么。我不能简单地转义整个表达式,否则我的变量将恢复为静态字符串“${temppasswd}”,这无济于事。我需要 ${temppasswd} 的值,即使它包含需要转义的字符。
帮忙?
this only happens when the output of slappasswd contains a /.
选择不同的 s
命令分隔符。像 ~
或任何其他字符。
sed -e "s~#userid#~${userid}~g"
在 GNU sed 的边缘情况下,您可以使用 any 字节,例如,您可以使用 C 转义 $'\x01'
来写入 0x01 字节:
sed -e $'s\x01#userid#\x01'"${userid}"$'\x01g'
但我建议不要重新发明轮子并使用现有的模板工具。将模板格式从 #userid#
更改为 ${userid}
,您可以使用 envsubst
.
使用 envsubst
和以下重新设计的模板:
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: ${userid}
gidNumber: ${gidnum}
givenName: ${firstname}
sn: ${lastname}
displayName: ${firstname} ${lastname}
homeDirectory: /home/${userid}
mail: ${userid}@nitssolutions.com
loginShell: /bin/bash
cn: ${firstname} ${lastname}
uidNumber: ${uidnum}
employeeType: INT-FT
employeeNumber: ${empno}
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: ${temppasswd}
已处理:program1
#!/usr/bin/env bash
Iam="${0##*/}" # Basename of myself
if [ $# -ne 6 ];
cat <<ERR >&2
$Iam: error: invalid number of arguments:
Usage:
$Iam <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>
ERR
exit 1
fi
userid="" firstname="" lastname="" \
gidnum="" uidnum="" empno="" \
temppasswd=$(slappasswd -s "pw4$userid") \
envsubst <user_tmpl.ldif
使用虚拟值测试 运行:
./program1 foo bar baz 666 42 99
foo bar baz 666 42 99 ciWatEpIcs
输出
dn: uid=foo,ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: foo
gidNumber: 666
givenName: bar
sn: baz
displayName: bar baz
homeDirectory: /home/foo
mail: foo@nitssolutions.com
loginShell: /bin/bash
cn: bar baz
uidNumber: 42
employeeType: INT-FT
employeeNumber: 99
dn: uid=foo,ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: ciWatEpIcs
现在有了一个简单的here文档,它甚至不需要envsubst
program2
:
#!/usr/bin/env bash
Iam="${0##*/}" # Basename of myself
if [ $# -ne 6 ];
then
cat <<ERR >&2
$Iam: error: invalid number of arguments:
Usage:
$Iam <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>
ERR
exit 1
fi
userid=
firstname=
lastname=
gidnum=
uidnum=
empno=
temppasswd=$(slappasswd -s "pw4$userid")
cat <<LDIFTEMPLATE
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: ${userid}
gidNumber: ${gidnum}
givenName: ${firstname}
sn: ${lastname}
displayName: ${firstname} ${lastname}
homeDirectory: /home/${userid}
mail: ${userid}@nitssolutions.com
loginShell: /bin/bash
cn: ${firstname} ${lastname}
uidNumber: ${uidnum}
employeeType: INT-FT
employeeNumber: ${empno}
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: ${temppasswd}
LDIFTEMPLATE