并非所有列(& data)都存在于所有记录中。因此,每当缺少字段缺失时,应将其替换为空值。
我的输入格式:
.set 1000
EMP_NAME="Rob"
EMP_DES="Developer"
EMP_DEP="Sales"
EMP_DOJ="20-10-2010"
EMR_MGR="Jack"
.set 1001
EMP_NAME="Koster"
EMP_DEP="Promotions"
EMP_DOJ="20-10-2011"
.set 1002
EMP_NAME="Boua"
EMP_DES="TA"
EMR_MGR="James"
我想要的输出格式:
Rob~Developer~Sales~20-10-2010~Jack
Koster~~Promotions~20-10-2011~
Boua~TA~~~James
我尝试了以下内容:
awk 'NR>1{printf "%s"(/^\.set/?RS:"~"),a} {a=substr($0,index($0,"=")+1)} END {print a}' $line
这是打印:
Rob~Developer~Sales~20-10-2010~Jack
Koster~Promotions~20-10-2011~
Boua~TA~James~
答案 0 :(得分:0)
这个awk脚本产生了所需的输出:
BEGIN { FS = "[=\"]+"; OFS = "~" }
/\.set/ { ++records; next }
NR > 1 { f[records,$1] = $2 }
END {
for (i = 1; i <= records; ++i) {
print f[i,"EMP_NAME"], f[i,"EMP_DES"], f[i,"EMP_DEP"], f[i,"EMP_DOJ"], f[i,"EMR_MGR"]
}
}
二维数组用于存储为每条记录定义的所有值。
在处理完所有文件后,循环遍历数组的每一行并打印所有值。未定义的元素将被计算为空字符串。
指定元素明确性允许您控制它们的打印顺序。使用print
而不是printf
可以正确使用已设置为OFS
的{{1}}变量,以及~
默认情况下换行符。
感谢his helpful comments的@Ed指出我原始剧本中的一些缺陷。
输出:
ORS
答案 1 :(得分:0)
$ cat tst.awk
BEGIN{ FS="[=\"]+"; OFS="~" }
/\.set/ { ++numRecs; next }
{ name2val[numRecs,$1] = $2 }
!seen[$1]++ { names[++numNames] = $1 }
END {
for (recNr=1; recNr<=numRecs; recNr++)
for (nameNr=1; nameNr<=numNames; nameNr++)
printf "%s%s", name2val[recNr,names[nameNr]], (nameNr<numNames?OFS:ORS)
}
$ awk -f tst.awk file
Rob~Developer~Sales~20-10-2010~Jack
Koster~~Promotions~20-10-2011~
Boua~TA~~~James
如果您希望输出中有一些预定义的字段顺序,而不是在读取时从每个记录中的行动态创建它,只需在BEGIN中显式填充names[]
数组部分,如果您有这种情况,并且不想将整个文件保存在内存中:
$ cat tst.awk
BEGIN{
FS="[=\"]+"; OFS="~";
numNames=split("EMP_NAME EMP_DES EMP_DEP EMP_DOJ EMR_MGR",names,/ /)
}
function prtName2val( nameNr, i) {
if ( length(name2val) ) {
for (nameNr=1; nameNr<=numNames; nameNr++)
printf "%s%s", name2val[names[nameNr]], (nameNr<numNames?OFS:ORS)
delete name2val
}
}
/\.set/ { prtName2val(); next }
{ name2val[$1] = $2 }
END { prtName2val() }
$ awk -f tst.awk file
Rob~Developer~Sales~20-10-2010~Jack
Koster~~Promotions~20-10-2011~
Boua~TA~~~James
以上使用length(name2val)
和delete name2val
的GNU awk,如果你没有,那么请使用for (i in name2val) { do stuff; break }
和split("",name2val)
代替..
答案 2 :(得分:-1)
这就是我所能建议的:
awk '{ t = $0; sub(/^[^"]*"/, "", t); gsub(/"[^"]*"/, "~", t); sub(/".*/, "", t); print t }' file
或sed:
sed -re 's|^[^"]*"||; s|"[^"]*"|~|g; s|".*||' file
输出:
Rob~Developer~Sales~20-10-2010~Jack~Koster~Promotions~20-10-2011~Boua~TA~James