以bash的特定顺序打印文件

时间:2019-02-08 12:45:04

标签: bash shell awk sed

我的文件包含以下内容:

file.txt:

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

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

Iteration 3
RAM: +184ms
Spec: +172ms
Searchms: +131ms (total +385ms)

First launch 4
RAM: +149ms
Searchms: +188ms

在此文件中,每个First launch之间的内容可以不同,它不是固定的(例如:第一次启动3包含三个元素,而第一次启动2内容仅包含2个元素),因此可以任意数量的内容在First launch模式之间(一开始是未知的)之间。

预期输出:

RAM  456 184 149
Cache 142 149  
Spec 152 172
Searchms 131 188

由于不知道确切的方法,我尝试了这段代码。

我的代码:

for i in {1..4}
do
awk "/First launch $i/{flag=1;next} /First launch $((i+1))/{flag=0} flag" file.txt> fl$i.txt
sed -i 's/\+//g' fl$i.txt
sed -i 's/://g' fl$i.txt
sed -i 's/(.*//g' fl$i.txt
sed -i 's/ms//g' fl$i.txt
awk '{print $1 "\t" $2}' fl$i.txt
done

我的输出有两个问题: 我正在为每种模式生成文件,这是错误的。我也想在此之后删除ms,但它也从模式名称中删除ms(例如:Searchms to Search)

输出:

fl1.txt: 
    RAM     456
    Cache   142
fl2.txt : 
    Spec    152
    Cache   149
fl3.txt  :
    RAM     184
    Spec    152
    Search  131
fl4.txt : 
    RAM     149
    Search  188

请向我建议一种获取预期输出而又不生成任何额外文件的方法,并且要在之后删除ms

6 个答案:

答案 0 :(得分:5)

使用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

以awk默认顺序输出的行(随机出现):

Cache: 142 149
Searchms: 131 188
Spec: 152 172
RAM: 456 184 149

答案 1 :(得分:4)

$ 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

答案 2 :(得分:2)

Perl一线:

$ 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

(行的顺序会有所不同;如果需要,可以用管道将其排序)


工作原理:

对于文件中的每一行,如果它与正则表达式^(\w+):\s+\+(\d)ms匹配(该行的开头为1个或更多字母数字字符,后接冒号,空格,加号,1个或多个数字,然后再加上字母m和s),它会使用起始单词作为键,将数字添加到哈希中的适当数组中。然后打印出所有这些起始词及其关联的数组。

与awk答案基本相同,但是使用字符串而不是数组,因为awk不像perl那样有真正的数组,而只有关联数组(在perl lingo中称为哈希)。

答案 3 :(得分:2)

这可能对您有用(GNU sed):

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

除包含:的行以外,其他任何行都是噪音,因此请将其删除。

从每行中删除除键,空格和第一组整数以外的所有内容。

将结果追加到保留空间。

使用模式匹配,像键数据一样收集并保留在保留空间中。

删除除最后一行以外的所有内容。

在文件末尾,交换到保留空间,删除引入的换行符并打印结果。

答案 4 :(得分:1)

另一个Perl,使用段落模式-00

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

带有输入

$ 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


$

答案 5 :(得分:0)

简单地:

#!/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

您可以在第2行中更改顺序(用于循环)

输出:

$ cat out.txt 
RAM 456 184 149 
Cache 142 417 149 413 
Spec 152 172 
Searchms 131 385 188