[英]How to extract specific lines from a file using bash
我正在研究一个脚本,该脚本应从命令结果中提取特定类型的用户及其对应的uidNumber并将其输出到文件中。 示例命令结果为:
dn: uid=test_user_2,ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot
cn: test_user_2
uid: test_user_2
uidNumber: 10000
gidNumber: 400
homeDirectory: /home/test_user_2
userPassword:: e2NyeXB0fSo=
dn: uid=test_user_3,ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot
cn: test_user_3
uid: test_user_3
uidNumber: 500
gidNumber: 400
homeDirectory: /home/test_user_2
userPassword:: e2NyeXB0fSo=
dn: cn=test_group_3,ou=Group,fsFragmentId=Security,fsClusterId=ClusterRoot
cn: test_group_3
gidNumber: 10000
homeDirectory: /home/test_user_3
userPassword:: e2NyeXB0fSo=
我想使用"ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot"
和uidNumber
(10000至60000)来打印所有用户
我已经使用"ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot"
提取了行,但是,我不知道如何提取其对应的uidNumber
我使用下面的命令:
$LDAP_command | grep "dn: uid=.*,ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot" > ldapsearch_extracted.txt
预期的输出应如下所示:
dn: uid=test_user_2,ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot
uidNumber: 10000
您可以尝试执行以下命令,
awk '
/ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot/{print}
/uidNumber/{if ($2>=10000 && $2<=60000)print}
' file
sed -n '/^\(dn\|uidNumber\):/H;/^$/ba;$ba;bb;:a;x;/uidNumber: [1-5][0-9]\{4\}\b/p;:b' <file.txt
dn: uid=test_user_2,ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot
uidNumber: 10000
要么
sed -n '/^\(dn:.*ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot\|uidNumber:\)/H;/^$/ba;$ba;bb;:a;x;/uidNumber: [1-5][0-9]\{4\}/p;:b' <file.txt
说明:
可以写成:
sed -n '
/^\(dn\|uidNumber\):/H;
/^$/ba;
$ba;
bb;
:a;
x;
/uidNumber: [1-5][0-9]\{4\}\b/p;
:b
' <file.txt
^dn:
或^uidNumber
,然后添加以保留空间 ^$
分支到标签:a
:a
:b
:a
uidNumber: [1-5][0-9]\\{4\\}
(包括10000
至59999
),则打印 :b
(循环到下一行) 要么
sed -n '
/^dn:.*ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot/H;
/^uidNumber:/H;
/^$/ba;
$ba;
bb;
:a;
x;
/uidNumber: [1-5][0-9]\{4\}\b/p;
:b
' <file.txt
sed -n '
/^\(dn\|uidNumber\|gidNumber\):/H;
/^$/ba;
$ba;
bb;
:a;
x;
/uidNumber: [1-5][0-9]\{4\}\b/{
/ou=People/{
/fsFragmentId=Security/{
/fsClusterId=ClusterRoot/{
p;
}
}
}
};
:b
' <file.txt
这将
这样做的主要优点是确保该工作与dn
行上的另一个变量顺序相同。
任何时候,只要输入中包含name = value配对,到目前为止,最清晰,最简单和最可扩展的方法是从创建一个包含该映射的数组开始(下面的f[]
),然后您可以按其名称访问值:
$ cat tst.awk
BEGIN { RS=""; FS=OFS="\n"; ORS="\n\n" }
{
delete f
for (i=1; i<=NF; i++) {
name = value = $i
sub(/:.*/,"",name)
sub(/^[^:]+:+[[:space:]]*/,"",value)
f[name] = value
}
}
(f["dn"] ~ /ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot/) &&
(f["uidNumber"]+0 >= 10000) && (f["uidNumber"]+0 <= 60000) {
print p("dn"), p("uidNumber")
}
function p(n) { return n ": " f[n] }
$ awk -f tst.awk file
dn: uid=test_user_2,ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot
uidNumber: 10000
显然,只要遵循上述结构,为实现其他条件和/或按自己喜欢的顺序打印其他字段所要做的其他任何事情都是完全不重要的。
是否要打印gidNumber
? 只需从以下命令更改打印语句:
print p("dn"), p("uidNumber")
至:
print p("dn"), p("uidNumber"), p("gidNumber")
要打印第二条记录吗? 只是改变
(f["dn"] ~ /ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot/) &&
(f["uidNumber"]+0 >= 10000) && (f["uidNumber"]+0 <= 60000) {
至:
NR==2 {
是否要在cn
== uid
位置打印记录? 将以上更改为:
f["cn"] == f["uid"] {
是否要打印未填充uidNumber
记录? 将以上更改为:
f["uidNumber"] == "" {
您可能想对字段的任何组合进行的操作以及所有其他操作都是显而易见,琐碎且一致的。
上面的代码在下面的文件上运行,您不需要前面的grep
或其他任何东西。
$ cat file
dn: uid=test_user_2,ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot
cn: test_user_2
uid: test_user_2
uidNumber: 10000
gidNumber: 400
homeDirectory: /home/test_user_2
userPassword:: e2NyeXB0fSo=
dn: uid=test_user_3,ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot
cn: test_user_3
uid: test_user_3
uidNumber: 500
gidNumber: 400
homeDirectory: /home/test_user_2
userPassword:: e2NyeXB0fSo=
dn: cn=test_group_3,ou=Group,fsFragmentId=Security,fsClusterId=ClusterRoot
cn: test_group_3
gidNumber: 10000
homeDirectory: /home/test_user_3
userPassword:: e2NyeXB0fSo=
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.