(sed/awk)提取值文本文件并写入csv(无模式)



我有(几个(大的文本文件,我想从中提取一些值来创建一个包含所有这些值的csv文件。

我目前的解决方案是对sed进行一些不同的调用,从中保存值,然后使用python脚本将不同文件中的数据组合为一个csv文件。然而,这相当慢,我想加快速度。

我们称之为my_file_1.txt的文件的结构类似于

lines I don't need
start value 123
lines I don't need
epoch 1
...
lines I don't need
some epoch 18 words
stop value 234
lines I don't need
words start value 345 more words
lines I don't need
epoch 1
...
lines I don't need
epoch 72
stop value 456
...

我想建造一个类似的东西

file,start,stop,epoch,run
my_file_1.txt,123,234,18,1
my_file_1.txt,345,456,72,2
...

我怎样才能得到我想要的结果?它不一定是Sed或Awk,只要我不需要安装新的东西,而且速度相当快。

我对awk没有任何经验。有了sed,我的最佳猜测是

filename=$1
echo 'file,start,stop,epoch,run' > my_data.csv
sed -n '
s/.*start value ([0-9]+).*/'"$filename"',1,/
h
$!N
/.*epoch ([0-9]+).*n.*stop value([0-9]+)/{s/2,1/}
D
T
G
P
' $filename | sed -z 's/,n/,/' >> my_data.csv

然后处理没有得到跑步次数的问题。此外,这并不完全正确,因为N将吞噬一些";起始值";导致错误结果的行。感觉用awk可以更容易地完成。

它类似于8992158,但我不能使用那个模式,我知道的awk太少,无法重写

解决方案(编辑(

我对这个问题的描述不够笼统,所以我把它改了一点,纠正了一些不一致的地方。

Awk(鲁斯蒂·勒穆尔的回答(

在这里,我从知道数字在行的末尾概括为使用gensub。为此,我应该指定的awk版本不是在所有版本中都可用。

BEGIN {
counter = 1 
OFS = ","   # This is the output field separator used by the print statement
print "file", "start", "stop", "epoch", "run"  # Print the header line
}
/start value/ {
startValue = gensub(/.*start value ([0-9]+).*/, "\1", 1, $0) 
}
/epoch/ {
epoch = gensub(/.*epoch ([0-9]+).*/, "\1", 1, $0) 
}
/stop value/ {
stopValue = gensub(/.*stop value ([0-9]+).*/, "\1", 1, $0) 

# we have everything to print our line
print FILENAME, startValue, stopValue, epoch, counter
counter = counter + 1 
startValue = "" # clear variables so they aren't maintained through the next iteration
epoch = ""
}

我接受了这个答案,因为这是可以理解的。

Sed(波通的回答(

sed -nE '1{x;s/^/file,start,stop,epock,run/p;s/.*/0/;x}
/^.*start value/{:a;N;/n.*stop value/!ba;x
s/.*/expr & + 1/e;x;G;F
s/^.*start value (S+).*n.*epoch (S+)n.*stop value (S+).*n(S+)/,1,3,2,4/p}' my_file_1.txt |         sed '1!N;s/n//'

目前尚不清楚如何从您提供的输入中获得您提供的输出,但这可能是您想要做的(在每个Unix盒子上的任何shell中使用任何awk(:

$ cat tst.awk
BEGIN {
OFS = ","
print "file", "start", "stop", "epoch", "run"
}
{ f[$1] = $NF }
$1 == "stop" {
print FILENAME, f["start"], f["stop"], f["epoch"], ++run
delete f
}

$ awk -f tst.awk my_file_1.txt
file,start,stop,epoch,run
my_file_1.txt,123,234,N,1
my_file_1.txt,345,456,M,2

awk的基本结构是:

  1. 从输入中读取记录(默认情况下,记录是一行(
  2. 评估条件
  3. 应用操作

记录被拆分为多个字段(默认情况下,基于空格作为分隔符(。字段按其位置引用,从1开始$1是第一个字段,2美元是第二个字段。最后一个字段由一个名为NF的变量引用;字段数"NF是最后一个字段,$(NF-1(是倒数第二个字段,等等。

A";BEGIN";节将在读取任何输入文件之前执行,它可以用于初始化变量(隐式初始化为0(。

BEGIN {
counter = 1
OFS = ","   # This is the output field separator used by the print statement
print "file", "start", "stop", "epoch", "run"  # Print the header line
}
/start value/ {
startValue = $NF  # when a line contains "start value" store the last field as startValue 
}
/epoch/ {
epoch = $NF
}
/stop value/ {
stopValue = $NF
# we have everything to print our line
print FILENAME, startValue, stopValue, epoch, counter
counter = counter + 1
startValue = "" # clear variables so they aren't maintained through the next iteration
epoch = ""
}

将其保存为processor.awk并调用为:

awk -f processor.awk my_file_1.txt my_file_2.txt my_file_3.txt > output.csv

这可能对你有用(GNU sed(:

sed -nE '1{x;s/^/file,start,stop,epock,run/p;s/.*/0/;x}
/^start value/{:a;N;/nstop value/!ba;x
s/.*/expr & + 1/e;x;G;F
s/^start value (S+).*nepoch (S+)nstop value (S+).*n(S+)/,1,3,2,4/p}' file |
sed '1!N;s/n//'

该解决方案包含两个sed调用,第一个用于格式化除文件名之外的所有文件,第二个用于将文件名嵌入csv文件。

在第一行设置标题行的格式,并对游程编号进行素数运算。

收集start valuestop value之间的线路。

增加行程编号,将其附加到当前行并输出文件名。这会为每条记录打印两行,第一行是文件名,第二行是csv文件的其余部分。

在第二个sed调用中,一次读取两行(第一行除外(,并删除它们之间的换行符,格式化csv文件。

最新更新