【问题标题】:Proper escape strategy for strings字符串的正确转义策略
【发布时间】:2020-11-18 15:54:48
【问题描述】:

我正在编写一个简单的 BASH 脚本来生成一个 LDIF 文件,然后我可以使用该文件将用户添加到我的 OpenLDAP 服务器。

这是脚本:

#!/bin/bash
#add LDAP user, v1.0, by mbobak, 11/17/2020
if [ $# != 6 ];
then
    echo "`basename $0`:  error:  invalid number of arguments:"
        echo "`basename $0` <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>"
    exit 1
fi
userid=$1
firstname=$2
lastname=$3
gidnum=$4
uidnum=$5
empno=$6
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} 的值,即使它包含需要转义的字符。

帮助?

【问题讨论】:

标签: linux bash sed escaping


【解决方案1】:

这只发生在 slappasswd 的输出包含 / 时。

选择不同的s 命令分隔符。像~ 或任何其他字符。

sed -e "s~#userid#~${userid}~g"

在 GNU sed 的边缘情况下,您可以使用 any 字节,例如,您可以使用 C 转义 $'\x01' 写入 0x01 字节:

sed -e $'s\x01#userid#\x01'"${userid}"$'\x01g'

但我建议不要重新发明轮子并使用现有的模板工具。将模板的格式从#userid# 更改为${userid},您可以使用envsubst

【讨论】:

  • 当然!我不敢相信我没有看到这个明显的答案.....谢谢!
【解决方案2】:

使用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="$1" firstname="$2" lastname="$3" \
gidnum="$4" uidnum="$5" empno="$6" \
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=$1
firstname=$2
lastname=$3
gidnum=$4
uidnum=$5
empno=$6
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

【讨论】:

  • 完美!感谢您提供完整的示例!实际上,我以前从未使用过 gettext 或 envsubst。非常好!
猜你喜欢
  • 2011-01-05
  • 2019-07-28
  • 2010-11-19
  • 2014-04-27
  • 1970-01-01
  • 2014-08-02
  • 2012-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多