0

我一直在做一些研究,但我认为这个问题非常特别。当条件匹配时,我想从文件中提取固定数量的行。假设文件如下所示:

19287.4342
23213.444443
Time = 0.1
333245.4324
0.2432421
98374532.3241
937463.41
82162.462
762542.16
452621.45
12.019288
Time = 0.2
93891.182
103837.3333
937382.32321
10383.32
163873.22
9821.001
83638.1209
443.232111
Time = 0.3
...

提取后我想每次都得到一个文件i。文件0.1.txt应该是:

937463.41
82162.462
762542.16
452621.45

并且0.2.txt

10383.32
163873.22
9821.001
83638.1209

所以我想在每行 where 之后提取区间 [4,7] 内的行Time = i,其中i从 0.1 到 10,增量为 0.1。另一种观点可能是跳过前 3 个数字 afterTime = i并跳过最后一个 before Time = i。但两者都导致相同的结果。

我认为这可以使用awk一个for循环来完成:

for i in {0.1..10..0.1}
do
awk -v t="${i}" '{if(($1=='Time') && ($3==t) print (here the interval I want);}' file > ${i}.txt
done
4

1 回答 1

1

虽然您的问题很难理解,但您似乎要求取每一Time = 0.1行,然后在该时间和下一次之间的每一行,提取由小写字符组成的每一行到一个文件名0.1.txt(派生自该Time = 0.1行)

添加您尝试的代码后,很明显您对awk字段有误解。$5您显示的输入文件中不存在(第五个字段)。最多有 3 个字段(使用默认的空格分隔符)

好消息是,如果我正确理解您的要求,那么做您需要的事情就很容易了。您只需从每行开始捕获第三个字段Time,然后连接".txt"以创建文件名即可。然后只需匹配包含的每一行[a-z][a-z]并将该行重定向到使用print.

例如,给定以下输入:

示例输入文件

$ cat file
111
222
Time = 0.1
333
444
555
aa
bb
cc
dd
666
Time = 0.2
333
444
555
aa

示例使用

您可以使用以下短调用awk

awk '
    $1 == "Time" { fname=$3 ".txt"; next }
    /[a-z][a-z]/ { print $0 > fname }
' file

示例输出文件

Time = 0.1(named )的文件"0.1.txt"将是:

$ cat 0.1.txt
aa
bb
cc
dd

Time = 0.2(名称:)的文件"0.2.txt"

$ cat 0.2.txt
aa

仔细查看,让我知道我是否理解您的问题,如果您对awk表达式有任何进一步的问题。


继第二次编辑

在澄清您不想要[a-z][a-z]最初显示的那样,而是想要每行后面的浮点数Time = ...之后,所需的更改很小。不要输出匹配的行,只需使用正则表达式[a-z][a-z]输出包含 a 的行。'.'[.]

输入文件

$ cat file2
111
222
Time = 0.1
333
444
555
937463.41
82162.462
762542.16
452621.45
666
Time = 0.2
333
444
555
10383.32
163873.22
9821.001
83638.1209
666

awk用法*

$ awk '$1 == "Time" {fname=$3 ".txt"; next} /[.]/{print $0 > fname}' file2

输出文件

$ cat 0.1.txt
937463.41
82162.462
762542.16
452621.45

$ cat 0.2.txt
10383.32
163873.22
9821.001
83638.1209

编辑三 - 在“时间”之后提取第 4-7 行

好的,既然你现在已经指定你希望在每行之后提取第 4-7"Time = ..."行,你可以做同样的事情,但是你不需要寻找字符或浮点数,你只需保留一个数字计数器行后的"Time = ..."行数,并将值输出到每个文件count > 3 && count < 8。例如:

awk -v count=8 '
    $1 == "Time" {fname=$3 ".txt"; count=1; next}
    count > 3 && count < 8 {print $0 > fname}
    {count++}
' file2

最初将计数器设置为不匹配任何内容。然后,当"Time = ..."遇到时,它会创建文件名并设置count=1. 该组将为读取的每条记录{count++}递增,并且该组在遇到第 4-7 行时提取它们。countcount > 3 && count < 8 {print $0 > fname}

示例输入文件

$ cat file2
19287.4342
23213.444443
Time = 0.1
333245.4324
0.2432421
98374532.3241
937463.41
82162.462
762542.16
452621.45
12.019288
Time = 0.2
93891.182
103837.3333
937382.32321
10383.32
163873.22
9821.001
83638.1209
443.232111

然后使用:

$ awk -v count=8 '
    $1 == "Time" {fname=$3 ".txt"; count=1; next}
    count > 3 && count < 8 {print $0 > fname}
    {count++}
' file2

将产生所需的输出文件:

示例输出文件

$ cat 0.1.txt
937463.41
82162.462
762542.16
452621.45

$ cat 0.2.txt
10383.32
163873.22
9821.001
83638.1209

希望我们现在已经解决了您需要解决的实际问题:)

于 2019-07-19T17:04:02.467 回答