我有配置文件customer.cfg,它有2个字段:描述和列长度 如下:
ID ; 10
First Name ; 20
Last Name ; 20
我还有一个庞大的数据文件customer.dat,其中包含我想要阅读的数据,如下所示:
1234567890John Armless
9 Eric Clapton
10 Roger Waters
我想输入LINE NUMBER,CONFIG_FILE_NAME和DATA_FILE_NAME,awk应该能够根据.cfg文件的格式定义打印大文件中的数据:
例如:
示例1
Input: 2,customer.cfg,customer.dat
Outputs:
DataFileName: customer.dat
Line: 2
ID:9
First Name:Eric
Last Name:Clapton
示例2:
Input:all,customer.cfg,customer.dat
Outputs:
DataFileName: customer.dat
Line: 1
ID:1234567890
First Name:John
Last Name:Armless
DataFileName: customer.dat
Line: 2
ID:9
First Name:Eric
Last Name:Clapton
DataFileName: customer.dat
Line: 3
ID:10
First Name:Roger
Last Name:Waters
我对其他文件也有同样的看法,例如products.cfg& products.dat等,但始终遵循与上述相同的标准。所以我想要一些通用的东西也可以用于其他文件。
Considerations:
- I want a solutions that uses AWK & printf
- I can't install anything on this server.
- My server is running AIX
答案 0 :(得分:3)
您可以尝试以下脚本:(如果您使用的是Gnu Awk第4版,则可以使用FIELDWIDTHS
而不是调用substr
来简化脚本。
#! /bin/bash
lineno=all
cfgfile="customer.cfg"
datfile="customer.dat"
awk -v line="$lineno" -f p.awk FS=";" "$cfgfile" "$datfile"
其中p.awk
是:
NR==FNR {
a[++i]=$2
next
}
line=="all" || FNR==line{
print "DataFileName: " FILENAME
print "Line "FNR
id=getField(1,a[1])
fn=getField(1+a[1],a[2])
ln=getField(1+a[1]+a[2],a[3])
print "ID:"id
print "First Name: "fn
print "Last Name: "ln
}
function getField(a,b,str) {
str=substr($0,a,b)
sub(/^[[:blank:]]+/,"",str)
sub(/[[:blank:]]$/,"",str)
return str
}
带输出:
DataFileName: customer.dat
Line 1
ID:1234567890
First Name: John
Last Name: Armless
DataFileName: customer.dat
Line 2
ID:9
First Name: Eric
Last Name: Clapton
DataFileName: customer.dat
Line 3
ID:10
First Name: Roger
Last Name: Waters
答案 1 :(得分:3)
这里有更通用的方法来处理它而无需对列名进行硬编码。这将允许在不同的文件上运行代码。
NF > 1 {
colwidth[FNR]=$2
colname[FNR]=$1
++colcount
}
NF < 2 {
if(line=="all" || FNR==line) {
printf("DataFileName: %s\n",FILENAME)
printf("Line %d\n",FNR)
nextcol=1
for(eachcol=1; eachcol <= colcount; eachcol++ ) {
printf("%s : %s\n",colname[eachcol],substr($0,nextcol,colwidth[eachcol]))
nextcol+=colwidth[eachcol]
}
}
}
这是我运行上述代码时得到的结果。我将代码保存为/tmp/p.awk。
**awk -v line=2 -f /tmp/p.awk -F";" /tmp/customer.cfg /tmp/customer.dat**
DataFileName: /tmp/customer.dat
Line 2
ID : 9
First Name : Eric
Last Name : Clapton
**awk -v line=all -f /tmp/p.awk -F";" /tmp/customer.cfg /tmp/customer.dat**
DataFileName: /tmp/customer.dat
Line 1
ID : 1234567890
First Name : John
Last Name : Armless
DataFileName: /tmp/customer.dat
Line 2
ID : 9
First Name : Eric
Last Name : Clapton
DataFileName: /tmp/customer.dat
Line 3
ID : 10
First Name : Roger
Last Name : Waters
答案 2 :(得分:2)
@HåkonHægland 我改变了一些你的代码以使其足够通用,所以现在我可以将它用于我在这里的任何* .dat * .cfg文件。
NR==FNR {
a[++i]=$2
b[i]=$1
next
}
line=="all" || FNR==line{
print "DataFileName: " FILENAME
print "Line: "FNR
linePos=1
for (j=1;j<=i;j++){
print b[j]":" getField(linePos,a[j])
linePos+=a[j]
}
print "\n"
}
function getField(a,b,str) {
str=substr($0,a,b)
sub(/^[[:blank:]]+/,"",str)
sub(/[[:blank:]]$/,"",str)
return str
}
再次感谢。