使用sed / awk来限制/解析LDAP DN的输出

时间:2011-12-28 17:13:17

标签: bash sed awk

我有一个很大的LDAP DN列表,因为它们无法导入到我的应用程序中。我需要根据CN的一个非常特定的部分对我的后端数据库进行查询,但是我不能完全确定如何将字符串限制为一个非常具体的值,该值不一定位于每次都是相同的位置。

使用以下bash命令:

grep 'Failed to process entry' /var/log/tomcat6/catalina.out | awk '{print substr($0, index($0,$14))}'

我可以返回类似于以下内容的DN列表:(对于编辑的性质,安全性要求而言很抱歉)

"cn=[Last Name] [Optional Middle Initial or Suffix] [First Name] [User name],ou=[value],ou=[value],o=[value],c=[value]".

CN值可能会令人困惑,因为如果值甚至存在,则可以按任何顺序显示姓氏,中间名,中间名或后缀的顺序,但有一点确实保持一致,用户名始终是最后一个字段在cn中(接着是","然后是许多潜在的OU中的第一个)。我需要解析用于查询的用户名,最好是用逗号分隔的列表,以便于复制和粘贴,以便在SQL IN()查询中使用或在bash脚本中使用。举个例子,想象下面的缩写DN的简短列表,只显示CN值(因为DN的其余部分无关紧要):

"cn=Doe Jr. John john.doe,ou=...".
"cn=Doe A. Jane jane.a.doe,ou=...".
"cn=Smith Bob J bsmith,ou=...".
"cn=Powers Richard richard.powers1,ou=...".

我想返回一个csv列表,如下所示:

john.doe,jane.a.doe,bsmith,richard.powers1

awk和/或sed的混合可以实现吗?

5 个答案:

答案 0 :(得分:1)

sed -e 's/"^[^,]* \([^ ,]*\),.*/\1/'

将解析公用名的用户名部分并隔离用户名。跟进

| tr '\n' , | sed -e 's/,$/\n/'

将每行一个用户名格式转换为逗号分隔格式。

答案 1 :(得分:0)

这是一种快速而又脏的方法 -

awk -v FS="[\"=,]" '{ print $3}' file | awk -v ORS="," '{print $NF}' | sed 's/,$//'

<强>测试

[jaypal:~/Temp] cat ff
"cn=Doe Jr. John john.doe,ou=...".
"cn=Doe A. Jane jane.a.doe,ou=...".
"cn=Smith Bob J bsmith,ou=...".
"cn=Powers Richard richard.powers1,ou=...".
[jaypal:~/Temp] awk -v FS="[\"=,]" '{ print $3}' ff | awk -v ORS="," '{print $NF}' | sed 's/,$//'
john.doe,jane.a.doe,bsmith,richard.powers1

如果你有gawk那么

gawk '{ print gensub(/.* (.*[^,]),.*/,"\\1","$0")}' filename | sed ':a;{N;s/\n/,/}; ba'

<强>测试

[jaypal:~/Temp] gawk '{ print gensub(/.* (.*[^,]),.*/,"\\1","$0")}' ff | sed ':a;{N;s/\n/,/}; ba'
john.doe,jane.a.doe,bsmith,richard.powers1

答案 2 :(得分:0)

给定一个包含

的文件“Document1.txt”

cn = Smith Jane batty.cow,ou = ou1_value,ou = oun_value,o = o_value,c = c_value

cn = Marley Bob reggae.boy,ou = ou1_value,ou = oun_value,o = o_value,c = c_value

cn = Clinton J Bill ex.president,ou = ou1_value,ou = oun_value,o = o_value,c = c_value

你可以做一个

cat Document1.txt | sed -e "s/^cn=.* \([A-Za-z0-9._]*\),ou=.*/\1/p"

让你

batty.cow

reggae.boy

ex.president

使用tr来转换行尾字符

cat Document1.txt | sed -n "s/^cn=.* \([A-Za-z0-9._]*\),ou=.*/\1/p" | tr '\n' ',' 

产生

batty.cow,reggae.boy,ex.president,

你将需要处理最后一个逗号

但是如果你想在数据库中说oracle例如,一个脚本包含:

#!/bin/bash
doc=$1
cat ${doc} | sed -e "s/^cn=.* \([A-Za-z0-9._]*\),ou=.*/\1/p" | while read username
    do
    sqlplus -s username/password@instance <<+++ insert into mytable (user_name) values ('${username}'\;)
    exit
    +++
done

N.B。 sed表达式中的A-Za-z0-9._是您在用户名中所期望的每种类型的角色 - 您可能需要使用该角色。

警告 - 我没有测试数据库插入的最后一位!

答案 3 :(得分:0)

我认为Perl正则表达式解决方案比其他选择更具可读性,以防您感兴趣:

perl -ne 'print "$1," if /(([[:alnum:]]|[[:punct:]])+),ou/' input.txt

打印'ou'之前的字符串,接受字母数字和标点符号字符(但没有空格,因此它停在用户名处)。

输出:

john.doe,jane.a.doe,bsmith,

答案 4 :(得分:0)

自从有一个想法发布到这个已经超过一年了,但是在将来再次出现这类问题时想要一个地方可以参考。另外,我没有看到类似的答案。

在提供的数据模式中,我的解释是我们可以在第一个逗号之后删除所有内容,为我们留下真正的CN,而不是以CN开头的DN。 在CN中,我们剥离了包括最后一个空格之前的所有内容。 这将为我们留下用户名。

awk -F','/ ^ cn = / {print $ 1}'ldapfile | awk'{print $ NF}'&gt;&gt;用户名

将ldap文件传递给awk,字段分隔符设置为逗号,匹配字符串设置为cn =在行的开头,我们将所有内容打印到第一个逗号。然后我们使用默认字段分隔符将输出管道输入到awk中,并仅打印最后一个字段,从而只输出用户名。我们将其重定向并将其附加到当前名为usernames的目录中的文件中,并且每行最终会有一个用户名。

要将此转换为单个逗号分隔的用户名行,我们将最后一个打印命令更改为printf,省略\ n换行符,但添加逗号。

awk -F','/ ^ cn = / {print $ 1}'ldapfile | awk'{printf $ NF“,”}'&gt;&gt; usersnames

这会在文件中留下一个带尾随逗号的唯一行,但由于它只用于剪切和粘贴,所以不要剪切最后一个字符。 :)