我正在尝试处理一堆使用gawk提取数据的文件。
文件区域固定宽度空格式文件
我正在尝试从两个不同的正则表达式匹配的两个不同行中提取数据,但是在ONE print语句中返回这两行中的数据。
我可以使用.awk
文件中的以下内容实现此目的,并使用gawk -f
来运行它。第一个BEGIN部分设置输入文件格式(FIELDWIDTHs)和第二个BEGIN我试图使用每个文件循环根据提取的数据输出。第一个END完成内部BEGIN,第二个END匹配外部BEGIN。
但是我一次只能将它应用到一个文件中,因为如果我应用于一堆文件(如gawk -f regex.awk km*.txt
中那样,我只得到最后一个文件的输出。
我是否可以为每个文件输入获得一行输出,而不必每次都使用循环输入文件并运行awk脚本的脚本文件。
由于
BEGIN{
OFS=","; FIELDWIDTHS ="2 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12";
printf("Date, Turnover, SalesA, SalesB, SalesC, SalesD, Other Data\n");
}
BEGIN{ Sales = 0;
SalesA = 0;
SalesB = 0;
SalesC = 0;
SalesD = 0;
JointSales = 0;
Turnover = 0;
OtherData = 0;}
/^03/ || /^06/ {
if ($1 == "03") {
Sales = $15/100;
SalesA = $17/100;
SalesB = $26/100;
SalesC = $20/100;
SalesD = $22/100;
JointSales = SalesA - SalesB;
Turnover = JointSales + SalesB + SalesC + SalesD; }
else if ( $1 == "06") {
OtherData = substr($0,183,12)/100; }
# printf("%s, %10.2f, %10.2f, %10.2f, %10.2f, %10.2f, %10.2f\n", getDate(FILENAME), Sales, JointSales, SalesB, SalesC, SalesD, OtherData )
}
END{printf("%s, %10.2f, %10.2f, %10.2f, %10.2f, %10.2f, %10.2f\n", getDate(FILENAME), Sales, JointSales, SalesB, SalesC, SalesD, OtherData ) }
END {}
function getDate(str)
{ date = substr(str,3,6);
year = substr(date,1,2);
month= substr(date,3,2);
day=substr(date,5,2);
odate=(day"/"month"/"year);
return odate
}
答案 0 :(得分:3)
如果您使用的是gawk
,那么您很幸运。除了BEGIN
和END
块之外,gawk
实现了BEGINFILE
和ENDFILE
块,它们可以按照您的需要执行:处理每个文件之前和之后。请参阅handy gawk programming guide。
与所有awk实现一样,Gnu awk允许您拥有多个BEGIN
和END
块。在读取第一个文件之前,所有BEGIN
块按顺序(从头到尾)运行,并且所有END
块在最后一个文件完成后以相同的倒数第一顺序运行。由于两种类型的特殊块使用相同的顺序,因此它们不会“嵌套”。
答案 1 :(得分:0)
awk
每次运行只允许一个begin
和end
动作集(尽管它们可以分布在多个块中,它们全部合并为一个动作集)和运行包括您处理的所有文件。
如果你想在每个文件之间做一些,可以使用ARGIND
变量来保存当前参数的索引(从零开始)。您只需要维护最后一个参数索引(最初为零),如果实际参数索引不同,则执行您的特殊操作并更新最后一个索引。
对于空文件(没有运行代码),当前参数索引可能比最后一个多一个,因此您可能需要循环,递增最后一个索引,直到达到现在的。
例如,让我们打印每个文件的行,但是在之前,之内和之后都有特殊标记。使用文件a.in
:
xyzzy
plugh
和一个不包含任何内容的b.in
文件,您可以使用以下脚本demo.awk
:
function middleCheck() {
while (lastArgInd != ARGIND) {
print "MIDDLE after "lastArgInd":"ARGV[lastArgInd]
lastArgInd++
}
}
BEGIN { print "BEGIN"
lastArgInd = 1
}
{ middleCheck()
print " "$0
}
END { middleCheck()
print "END"
}
在每个文件之间实现操作:
pax> vi demo.awk ; awk -f demo.awk b.in a.in a.in b.in a.in b.in b.in
BEGIN
MIDDLE after 1:b.in
xyzzy
plugh
MIDDLE after 2:a.in
xyzzy
plugh
MIDDLE after 3:a.in
MIDDLE after 4:b.in
xyzzy
plugh
MIDDLE after 5:a.in
MIDDLE after 6:b.in
END
你必须让你的行动符合你的需要,你现在的内心和内心的#34; end
紧随你当前的内心" begin
。