如何使用bash从文件中提取特定行

时间:2017-06-13 06:50:58

标签: linux bash shell awk grep

我正在编写一个脚本,该脚本应该从命令结果中提取特定类型的用户及其对应的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

3 个答案:

答案 0 :(得分:0)

您可以尝试以下命令,

awk '
  /ou=People,fsFragmentId=Security,fsClusterId=ClusterRoot/{print} 
  /uidNumber/{if ($2>=10000 && $2<=60000)print}
' file

答案 1 :(得分:0)

使用

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\}(包括1000059999),则打印
  • 标签 :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,uidNumber和gidNumber存储在保留空间中
  • 在最后一行或空行,如果uidNumber:[1-5] [0-9] {4}(包括10000到59999),那么
    • 如果ou =人,那么
      • 如果fsFragmentId =安全,那么
        • 如果fsClusterId = ClusterRoot,则打印。

这样做的主要优点是确保在dn行上使用另一个变量顺序。

答案 2 :(得分:0)

任何时候你的输入中都有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语句:

    print p("dn"), p("uidNumber")

为:

    print p("dn"), p("uidNumber"), p("gidNumber")

想要打印第2条记录吗?只是改变

(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=