如何将 awk 命令应用于由另一个 awk 命令定义的字段?
How to apply an awk command to a field defined by another awk command?
我有 2 个任务要对由字段分隔的数据字符串执行,我可以分别为每个任务提出一个 awk 命令,但我需要的是将第二个任务应用于第三个字段,并让第一项任务结果中的第二项任务结果。
文件中的数据data.csv
31;Area A;Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676);German;;;0;;Wolfgang Mozart
第一个任务是生成一个 xml 结构,这是通过下一个 awk 命令完成的:
awk -F';' -v OFS=';' '{printf "<A>\n\t<T>%s</T>\n\t<S>%s</S>\n\t<AT>%s</AT>\n\t<D>%s</D>\n\t<Id>%s</Id>\n</A>\n", ,,,,,}' test.csv
结果是:
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<D>0</D>
<Id>31</Id>
</A>
第二个任务是将格式为“[0-9]{4}-[1-5]”的每个代码转换为 <AT>
标签,我可以使用下一个命令来管理它:
awk 'BEGIN{FPAT="[0-9]{4}-[1-5]"} {for (i=1; i <= NF; i++) print "<AT>"$i"</AT>"}' test.csv
结果是(顺便说一句,我无法完成重复时只打印出一个实例):
<AT>3343-1</AT>
<AT>3343-1</AT>
<AT>3345-1</AT>
期望的输出是:
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3343-1</AT>
<AT>3345-1</AT>
<D>0</D>
<Id>31</Id>
</A>
我能想到的最好的命令是下一个,它没有产生所需的输出:
awk -F';' -v OFS=';' 'BEGIN{FPAT="[0-9]{4}-[1-5]"} {for (i=1; i <= NF; i++) printf "<A>\n\t<T>%s</T>\n\t<S>%s</S>\n\t<AT>%s</AT>\n\t<D>%s</D>\n\t<Id>%s</Id>\n</A>\n", ,,,,,}' test.csv
结果是:
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3343-1</AT>
<D>0</D>
<Id>31</Id>
</A>
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3343-1</AT>
<D>0</D>
<Id>31</Id>
</A>
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3345-1</AT>
<D>0</D>
<Id>31</Id>
</A>
一个想法使用 GNU awk
:
awk -F';' '
{ patsplit(,arr,"[0-9]{4}-[1-5]") # split field #3 into NNNN-N strings
delete seen # clear seen[] array
for (i in arr) # for each NNNN-N string in arr[], store as index in
seen[arr[i]] # seen[] array; duplicates are effectively eliminated
printf "<A>\n\t<T>%s</T>\n\t<S>%s</S>\n\t<AT>%s</AT>\n", ,,
PROCINFO["sorted_in"]="@ind_str_asc" # assuming we want NNNN-N strings displayed in sorted order
for (at in seen)
printf "\t<AT>%s</AT>\n", at
printf "\t<D>%s</D>\n\t<Id>%s</Id>\n</A>\n", ,
}
' data.csv
这会生成:
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3343-1</AT>
<AT>3345-1</AT>
<D>0</D>
<Id>31</Id>
</A>
我有 2 个任务要对由字段分隔的数据字符串执行,我可以分别为每个任务提出一个 awk 命令,但我需要的是将第二个任务应用于第三个字段,并让第一项任务结果中的第二项任务结果。
文件中的数据data.csv
31;Area A;Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676);German;;;0;;Wolfgang Mozart
第一个任务是生成一个 xml 结构,这是通过下一个 awk 命令完成的:
awk -F';' -v OFS=';' '{printf "<A>\n\t<T>%s</T>\n\t<S>%s</S>\n\t<AT>%s</AT>\n\t<D>%s</D>\n\t<Id>%s</Id>\n</A>\n", ,,,,,}' test.csv
结果是:
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<D>0</D>
<Id>31</Id>
</A>
第二个任务是将格式为“[0-9]{4}-[1-5]”的每个代码转换为 <AT>
标签,我可以使用下一个命令来管理它:
awk 'BEGIN{FPAT="[0-9]{4}-[1-5]"} {for (i=1; i <= NF; i++) print "<AT>"$i"</AT>"}' test.csv
结果是(顺便说一句,我无法完成重复时只打印出一个实例):
<AT>3343-1</AT>
<AT>3343-1</AT>
<AT>3345-1</AT>
期望的输出是:
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3343-1</AT>
<AT>3345-1</AT>
<D>0</D>
<Id>31</Id>
</A>
我能想到的最好的命令是下一个,它没有产生所需的输出:
awk -F';' -v OFS=';' 'BEGIN{FPAT="[0-9]{4}-[1-5]"} {for (i=1; i <= NF; i++) printf "<A>\n\t<T>%s</T>\n\t<S>%s</S>\n\t<AT>%s</AT>\n\t<D>%s</D>\n\t<Id>%s</Id>\n</A>\n", ,,,,,}' test.csv
结果是:
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3343-1</AT>
<D>0</D>
<Id>31</Id>
</A>
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3343-1</AT>
<D>0</D>
<Id>31</Id>
</A>
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3345-1</AT>
<D>0</D>
<Id>31</Id>
</A>
一个想法使用 GNU awk
:
awk -F';' '
{ patsplit(,arr,"[0-9]{4}-[1-5]") # split field #3 into NNNN-N strings
delete seen # clear seen[] array
for (i in arr) # for each NNNN-N string in arr[], store as index in
seen[arr[i]] # seen[] array; duplicates are effectively eliminated
printf "<A>\n\t<T>%s</T>\n\t<S>%s</S>\n\t<AT>%s</AT>\n", ,,
PROCINFO["sorted_in"]="@ind_str_asc" # assuming we want NNNN-N strings displayed in sorted order
for (at in seen)
printf "\t<AT>%s</AT>\n", at
printf "\t<D>%s</D>\n\t<Id>%s</Id>\n</A>\n", ,
}
' data.csv
这会生成:
<A>
<T>Wolfgang Mozart</T>
<S>Language B1 G1-T1-(3343-1-25274)+(3343-1-25278)+(3345-1-25676)</S>
<AT>Area A</AT>
<AT>3343-1</AT>
<AT>3345-1</AT>
<D>0</D>
<Id>31</Id>
</A>