Print file in particular order in bash

前端 未结 6 406
谎友^
谎友^ 2021-01-13 13:22

I have file with content:

file.txt:

Iteration 1
RAM: +456ms
Cache: +142ms (total +417ms)

Iteration 2
Spec: +152ms
Cache: +149ms (total +413ms)

Iter         


        
相关标签:
6条回答
  • 2021-01-13 13:40

    One using awk:

    $ awk '
    $1 !~ /^(|First)$/ {            # avoid forbidden keywords and empty lines
        gsub(/[^0-9]/,"",$2)        # remove non-numerals
        a[$1]=a[$1] OFS $2          # append to associative array 
    }
    END {                           # in the end
        for(i in a)                 # loop all keywords
            print i a[i]            # output
    }' file
    

    Output lines in awk default order (appears random):

    Cache: 142 149
    Searchms: 131 188
    Spec: 152 172
    RAM: 456 184 149
    
    0 讨论(0)
  • 2021-01-13 13:40

    Simply:

    #!/bin/bash
    for i in RAM Cache Spec Searchms; do
        echo "$i `cat file.txt  | grep $i | grep -Eo '[0-9]{1,9}' | tr '\n' ' '`" >> out.txt
    done
    

    You can change the order in line 2 ( for loop )

    Output:

    $ cat out.txt 
    RAM 456 184 149 
    Cache 142 417 149 413 
    Spec 152 172 
    Searchms 131 385 188 
    
    0 讨论(0)
  • 2021-01-13 13:44
    $ cat tst.awk
    BEGIN { FS="[: ]+" }
    /:/ { vals[$1] = vals[$1] OFS $2+0 }
    END { for (key in vals) print key vals[key] }
    
    $ awk -f tst.awk file
    Cache 142 149
    RAM 456 184 149
    Searchms 131 188
    Spec 152 172
    
    0 讨论(0)
  • 2021-01-13 13:45

    This might work for you (GNU sed):

    sed -E '/:/!d;s/.([0-9]+).*/\1/;H;x;s/((\n\S+) \S+)(.*)\2(.*)/\1\4\3/;h;$!d;x;s/.//' file
    

    Any lines other than those that contain a : are noise, so delete them.

    Remove all but the key, a space and the first set of integers from each line.

    Append the result to the hold space.

    Using pattern matching, gather up like keys data and retain in the hold space.

    Delete all but the last line.

    At the end of file, swap to the hold space, remove the introduced newline and print the result.

    0 讨论(0)
  • 2021-01-13 13:50

    Perl one-liner:

    $ perl -nE 'if (/^(\w+):\s+\+(\d+)ms/) { push @{$keys{$1}}, $2 } END { while (($k, $vs) = each %keys) { say join(" ", $k, @$vs) }}' file.txt
    Spec 152 172
    Searchms 131 188
    Cache 142 149
    RAM 456 184 149
    

    (Order of the lines will vary; pipe it to sort if that matters)


    How it works:

    For each line in the file, if it matches the regular expression ^(\w+):\s+\+(\d)ms (1 or more alphanumeric characters at the start of the line, followed by a colon, whitespace, a plus sign, 1 or more digits, and then the letters m and s), it adds the number to the appropriate array in a hash using the starting word as the key. Then it prints out all those starting words and their associated arrays.

    Basically the same idea as the awk answer, but that uses strings instead of arrays because awk doesn't have true arrays like perl, just associative ones (Which are called hashes in perl lingo).

    0 讨论(0)
  • 2021-01-13 13:51

    Another Perl, using paragraph mode -00

    perl -00 -lnE ' 
                   while(/(^\S+):.+?(\d+)/gm ) {push(@{$kv{$1}},$2)} 
                END { foreach(keys %kv) { print "$_ @{$kv{$_}}" } }    '
    

    with inputs

    $ cat arya.txt
    First launch 1
    RAM: +456ms
    Cache: +142ms (total +417ms)
    
    First launch 2
    Spec: +152ms
    Cache: +149ms (total +413ms)
    
    First launch 3
    RAM: +184ms
    Spec: +172ms
    Searchms: +131ms (total +385ms)
    
    First launch 4
    RAM: +149ms
    Searchms: +188ms
    
    $ perl -00 -lnE ' while(/(^\S+):.+?(\d+)/gm ) {push(@{$kv{$1}},$2)} END { foreach(keys %kv) { print "$_ @{$kv{$_}}" } } ' arya.txt
    RAM 456 184 149
    
    Cache 142 149
    
    Searchms 131 188
    
    Spec 152 172
    
    
    $
    
    0 讨论(0)
提交回复
热议问题