【问题标题】:can awk replace fields based on separate specification file?awk 可以根据单独的规范文件替换字段吗?
【发布时间】:2012-01-28 17:37:17
【问题描述】:

我有一个这样的输入文件:

SomeSection.Foo
OtherSection.Foo
OtherSection.Goo

...还有另一个文件描述了哪些对象属于每个部分:

[SomeSection]
Blah
Foo
[OtherSection]
Foo
Goo

期望的输出是:

SomeSection.2   // that's because Foo appears 2nd in SomeSection
OtherSection.1  // that's because Foo appears 1st in OtherSection
OtherSection.2  // that's because Goo appears 2nd in OtherSection

(节和对象的数量和名称是可变的)

你会如何在 awk 中做这样的事情?

提前致谢, 阿德里安。

【问题讨论】:

    标签: awk getline


    【解决方案1】:

    一种可能性:

    script.awk 的内容(带有 cmets):

    ## When 'FNR == NR', the first input file is in process.                                                                                                                                                                                     
    ## If line begins with '[', get the section string and reset the position                                                                                                                                                                           
    ## of its objects.                                                                                                                                                                                                                           
    FNR == NR && $0 ~ /^\[/ {                                                                                                                                                                                                                    
            object = substr( $0, 2, length($0) - 2 )                                                                                                                                                                                             
            pos = 0
            next
    }
    
    ## This section process the objects of each section. It saves them in
    ## an array. Variable 'pos' increments with each object processed.
    FNR == NR {
            arr_obj[object, $0] = ++pos
            next
    }
    
    ## This section process second file. It splits line in '.' to find second
    ## part in the array and prints all.
    FNR < NR {
            ret = split( $0, obj, /\./ )
            if ( ret != 2 ) {
                    next
            }
            printf "%s.%d\n", obj[1], arr_obj[ obj[1] SUBSEP obj[2] ]
    }
    

    运行脚本(输入文件的顺序很重要,object.txt 包含对象部分和 input.txt 调用部分):

    awk -f script.awk object.txt input.txt
    

    结果:

    SomeSection.2
    OtherSection.1
    OtherSection.2
    

    编辑到 cmets 中的一个问题:

    我不是专家,但我会尝试解释我是如何理解它的:

    SUBSEP 是当您想使用不同的值作为键时分隔数组中索引的字符。默认为\034,但您可以修改为RSFS

    在指令arr_obj[object, $0] = ++pos 中,逗号将所有值与SUBSEP 的值连接起来,因此在这种情况下会导致:

    arr_obj[SomeSection\034Blah] = 1
    

    在脚本的末尾,我使用变量arr_obj[ obj[1] SUBSEP obj[2] 显式访问索引,但与上一节中的arr_obj[object, $0] 具有相同的含义。

    您还可以访问该索引的每个部分,使用 SUBSEP 变量将其拆分,如下所示:

    for (key in arr_obj) {                     ## Assign 'string\034string' to 'key' variable
        split( key, key_parts, SUBSEP )        ## Split 'key' with the content of SUBSEP variable.
        ...
    }
    

    结果为:

    key_parts[1] -> SomeSection
    key_parts[2] -> Blah
    

    【讨论】:

    • 你能解释一下你脚本的最后一部分吗?我总是最难处理数组。
    • @JaypalSingh:更新了答案来解释它。
    【解决方案2】:

    这条 awk 行应该可以完成这项工作:

     awk  'BEGIN{FS="[\\.\\]\\[]"}
            NR==FNR{ if(NF>1){ i=1; idx=$2; }else{ s[idx"."$1]=i; i++; } next; }
            { if($0 in s) print $1"."s[$0] } ' f2 input
    

    请看下面的测试:

    kent$  head input f2
    ==> input <==
    SomeSection.Foo
    OtherSection.Foo
    OtherSection.Goo
    
    ==> f2 <==
    [SomeSection]
    Blah
    Foo
    [OtherSection]
    Foo
    Goo
    
    kent$  awk  'BEGIN{FS="[\\.\\]\\[]"}
            NR==FNR{ if(NF>1){ i=1; idx=$2; }else{ s[idx"."$1]=i; i++; } next; }
            { if($0 in s) print $1"."s[$0] } ' f2 input
    SomeSection.2
    OtherSection.1
    OtherSection.2
    

    【讨论】:

      猜你喜欢
      • 2013-09-07
      • 2014-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-16
      • 2021-03-24
      • 2019-08-04
      • 2018-05-30
      相关资源
      最近更新 更多