使用 bash 解析 ldapsearch 的输出
Using bash to parse the output of ldapsearch
我最近写了一个 bash 脚本,它必须解析 ldapsearch 结果的输出。该脚本有效,但我认为有更有效的方法来完成此操作。
该脚本执行一个 ldapsearch 命令,该命令以多行格式输出多条记录。每条记录由一个空行分隔。我最终做了以下事情:
- 在每行的末尾添加一个分隔符
- 将字符串'DELIM'添加到空白行
- 修剪所有新行
- 用新行替换了'DELIM'
这有效地将 ldapsearch 的多行输出转换为多行分隔值。然后我使用 cut 两次来解析行(一次分割分隔符,然后再次吐出 ldap 结果的输出)
代码如下:
while IFS= read -r line ; do
dn=$(echo "$line" | cut -d '#' -f 1 | cut -d " " -f 2)
uid=$(echo "$line" | cut -d '#' -f 2 | cut -d " " -f 2)
uidNumber=$(echo "$line" | cut -d '#' -f 3 | cut -d " " -f 2)
gidNumber=$(echo "$line" | cut -d '#' -f 4 | cut -d " " -f 2)
# Code emitted since it's not relevant
done < <(ldapsearch -x -H "$ldap_server" -D 'cn=Directory Manager' -w $ds_password -b "$searchbase" -LLL uid uidNumber gidNumber | sed 's/$/#/g' | sed 's/^#$/DELIM/g' | tr -d '\n' | sed 's/DELIM/\n/g')
ldapsearch 命令的输出如下
dn: uid=userone,ou=People,dc=team,dc=company,dc=local
uid: userone
uidNumber: 5000
gidNumber: 5000
dn: uid=usertwo,ou=People,dc=team,dc=company,dc=local
uid: usertwo
uidNumber: 5001
gidNumber: 5001
有没有更有效的方法来完成这个?特别是一个不那么广泛使用管道的人?
你可以玩玩awk
ldap search | awk '=' RS= ORS='\n' OFS='#'
dn: uid=userone,ou=People,dc=team,dc=company,dc=local#uid: userone#uidNumber: 5000#gidNumber: 5000
dn: uid=usertwo,ou=People,dc=team,dc=company,dc=local#uid: usertwo#uidNumber: 5001#gidNumber: 5001
RS=
将记录选择器设置为空(将 awk 设置为块模式)(通常是每一行)
ORS='\n'
将输出记录选择器设置为新行
OFS='#'
将输出字段分隔符设置为 #
=
重新创建该行并打印它。
使用这个可能更安全:
awk '{=}1' RS= ORS='\n' OFS='#'
假设:
- ldapsearch数据不包含白色space(s)
- 将数据重新格式化为单行(通过 OP 的当前代码或通过 jotne 的回答)包括将
#
分隔符替换为 space (
)
使用 space(而不是 #
)作为分隔符,我们得到以下重新格式化的 ldapsearch
数据(8x space 分隔字段):
dn: uid=userone,ou=People,dc=team,dc=company,dc=local uid: userone uidNumber: 5000 gidNumber: 5000
dn: uid=usertwo,ou=People,dc=team,dc=company,dc=local uid: usertwo uidNumber: 5001 gidNumber: 5001
可以修改 while read
操作以消除每次通过 while
循环时的(当前)12x 子进程调用 (4x $(echo|cut|cut)
),例如:
while read -r _ dn _ uid _ uidNumber _ gidNumber
do
echo "############"
echo ".$dn."
echo ".$uid."
echo ".$uidNumber."
echo ".$gidNumber."
done < <(ldapsearch ... | other_code_to_reformat_ldapsearch_data_as_single_lines_but_with_space_delimiter)
备注:
_
是我们不关心的字段的虚拟占位符
- 句点 (
.
) 添加到 echo
语句作为视觉分隔符
这会生成:
############
.uid=userone,ou=People,dc=team,dc=company,dc=local.
.userone.
.5000.
.5000.
############
.uid=usertwo,ou=People,dc=team,dc=company,dc=local.
.usertwo.
.5001.
.5001.
另一个 awk
重新格式化 ldapsearch
结果的想法,它只输出我们感兴趣的字段:
awk '{for (i=2;i<=NF;i=i+2) {printf (i==2 ? "" : " ") $i}; print ""}' RS= ORS='\n'
其中:
- 我们重新使用 jotne 的
RS/ORS
设置
(i=2;i<=NF,i=i+2)
- 只打印偶数字段
这会生成:
uid=userone,ou=People,dc=team,dc=company,dc=local userone 5000 5000
uid=usertwo,ou=People,dc=team,dc=company,dc=local usertwo 5001 5001
通过此更改(4x space 分隔字段而不是 8x space 分隔字段)建议的 while read
变为:
while read -r dn uid uidNumber gidNumber
do
....
done < <(ldapsearch ... | awk '{for (i=2;i<=NF;i=i+2) {printf (i==2 ? "" : " ") $i}; print ""}' RS= ORS='\n')
我最近写了一个 bash 脚本,它必须解析 ldapsearch 结果的输出。该脚本有效,但我认为有更有效的方法来完成此操作。
该脚本执行一个 ldapsearch 命令,该命令以多行格式输出多条记录。每条记录由一个空行分隔。我最终做了以下事情:
- 在每行的末尾添加一个分隔符
- 将字符串'DELIM'添加到空白行
- 修剪所有新行
- 用新行替换了'DELIM'
这有效地将 ldapsearch 的多行输出转换为多行分隔值。然后我使用 cut 两次来解析行(一次分割分隔符,然后再次吐出 ldap 结果的输出)
代码如下:
while IFS= read -r line ; do
dn=$(echo "$line" | cut -d '#' -f 1 | cut -d " " -f 2)
uid=$(echo "$line" | cut -d '#' -f 2 | cut -d " " -f 2)
uidNumber=$(echo "$line" | cut -d '#' -f 3 | cut -d " " -f 2)
gidNumber=$(echo "$line" | cut -d '#' -f 4 | cut -d " " -f 2)
# Code emitted since it's not relevant
done < <(ldapsearch -x -H "$ldap_server" -D 'cn=Directory Manager' -w $ds_password -b "$searchbase" -LLL uid uidNumber gidNumber | sed 's/$/#/g' | sed 's/^#$/DELIM/g' | tr -d '\n' | sed 's/DELIM/\n/g')
ldapsearch 命令的输出如下
dn: uid=userone,ou=People,dc=team,dc=company,dc=local
uid: userone
uidNumber: 5000
gidNumber: 5000
dn: uid=usertwo,ou=People,dc=team,dc=company,dc=local
uid: usertwo
uidNumber: 5001
gidNumber: 5001
有没有更有效的方法来完成这个?特别是一个不那么广泛使用管道的人?
你可以玩玩awk
ldap search | awk '=' RS= ORS='\n' OFS='#'
dn: uid=userone,ou=People,dc=team,dc=company,dc=local#uid: userone#uidNumber: 5000#gidNumber: 5000
dn: uid=usertwo,ou=People,dc=team,dc=company,dc=local#uid: usertwo#uidNumber: 5001#gidNumber: 5001
RS=
将记录选择器设置为空(将 awk 设置为块模式)(通常是每一行)
ORS='\n'
将输出记录选择器设置为新行
OFS='#'
将输出字段分隔符设置为 #
=
重新创建该行并打印它。
使用这个可能更安全:
awk '{=}1' RS= ORS='\n' OFS='#'
假设:
- ldapsearch数据不包含白色space(s)
- 将数据重新格式化为单行(通过 OP 的当前代码或通过 jotne 的回答)包括将
#
分隔符替换为 space (
使用 space(而不是 #
)作为分隔符,我们得到以下重新格式化的 ldapsearch
数据(8x space 分隔字段):
dn: uid=userone,ou=People,dc=team,dc=company,dc=local uid: userone uidNumber: 5000 gidNumber: 5000
dn: uid=usertwo,ou=People,dc=team,dc=company,dc=local uid: usertwo uidNumber: 5001 gidNumber: 5001
可以修改 while read
操作以消除每次通过 while
循环时的(当前)12x 子进程调用 (4x $(echo|cut|cut)
),例如:
while read -r _ dn _ uid _ uidNumber _ gidNumber
do
echo "############"
echo ".$dn."
echo ".$uid."
echo ".$uidNumber."
echo ".$gidNumber."
done < <(ldapsearch ... | other_code_to_reformat_ldapsearch_data_as_single_lines_but_with_space_delimiter)
备注:
_
是我们不关心的字段的虚拟占位符- 句点 (
.
) 添加到echo
语句作为视觉分隔符
这会生成:
############
.uid=userone,ou=People,dc=team,dc=company,dc=local.
.userone.
.5000.
.5000.
############
.uid=usertwo,ou=People,dc=team,dc=company,dc=local.
.usertwo.
.5001.
.5001.
另一个 awk
重新格式化 ldapsearch
结果的想法,它只输出我们感兴趣的字段:
awk '{for (i=2;i<=NF;i=i+2) {printf (i==2 ? "" : " ") $i}; print ""}' RS= ORS='\n'
其中:
- 我们重新使用 jotne 的
RS/ORS
设置 (i=2;i<=NF,i=i+2)
- 只打印偶数字段
这会生成:
uid=userone,ou=People,dc=team,dc=company,dc=local userone 5000 5000
uid=usertwo,ou=People,dc=team,dc=company,dc=local usertwo 5001 5001
通过此更改(4x space 分隔字段而不是 8x space 分隔字段)建议的 while read
变为:
while read -r dn uid uidNumber gidNumber
do
....
done < <(ldapsearch ... | awk '{for (i=2;i<=NF;i=i+2) {printf (i==2 ? "" : " ") $i}; print ""}' RS= ORS='\n')