如何使用awk将文件内容的标题转换为列?

时间:2017-03-08 10:43:36

标签: arrays bash awk

我正在尝试使用awk将文件内容的标题转换为列,下面是我的输入文件 -

abc.txt
1234|43245
4325|65123
5432|12342
bcd.txt
865|432
324|543
123|654
cde.txt
12|321
21|123
32|123

输出:

abc.txt|1234|43245
abc.txt|4325|65123
abc.txt|5432|12342

bcd.txt|865|432
bcd.txt|324|543
bcd.txt|123|654

cde.txt|12|321
cde.txt|21|123
cde.txt|32|123

说明: 获取NR==1所在的文件名(abc.txt)并将其放入数组a或变量中并将其打印到文件内容中,并在文件内容完成后创建一个空行。

我尝试为a创建两个数组NF=1,为b创建另一个数组NF>1,并在数组b上循环以合并文件内容数组a但仍试图找出解决方案。

4 个答案:

答案 0 :(得分:4)

在awk中:

$ awk 'BEGIN{FS=OFS="|"} NF==1{h=$0} {print (NF==1?"": h OFS $0)}' file

abc.txt|1234|43245
abc.txt|4325|65123
abc.txt|5432|12342

bcd.txt|865|432
bcd.txt|324|543
bcd.txt|123|654

cde.txt|12|321
cde.txt|21|123
cde.txt|32|123

下行是,它在开头打印一个空行。如果您不能忍受,请在NR==1{next}阻止之前添加print - 或者更好:请参阅下面的@EdMorton's comment

说明:

BEGIN{ FS=OFS="|" }                # set delimiters
NF==1{ h=$0 }                      # if NF==1 it's header time, store it to h
# NR==1{ next }                    # to remove the leading enter, apply this
{ print (NF==1 ? "" : h OFS $0) }  # print an empty record or the record with header

答案 1 :(得分:1)

所以这是我的解决方案:

 awk 'BEGIN{ OFS = "|"} /[a-z].[a-z]/{ if ($0 != header && NR > 1){print ""}; header = $0 }/[0-9]\|[0-9]/{ numbers = $0; print header, numbers }' yourfile

输出:

abc.txt|1234|43245
abc.txt|4325|65123
abc.txt|5432|12342

bcd.txt|865|432
bcd.txt|324|543
bcd.txt|123|654

cde.txt|12|321
cde.txt|21|123
cde.txt|32|123

它没有任何数组,但它似乎工作。

答案 2 :(得分:1)

使用以下awk方法:

awk '{ if($1~/[a-z]+.txt/) { if(NR != 1) {print ""} h=$1;next } print h"|"$1;}' testfile

输出:

abc.txt|1234|43245
abc.txt|4325|65123
abc.txt|5432|12342

bcd.txt|865|432
bcd.txt|324|543
bcd.txt|123|654

cde.txt|12|321
cde.txt|21|123
cde.txt|32|123

说明:

if($1~/[a-z]+.txt/) - 条件检查当前列$1是否与模式/[a-z]+.txt/匹配(标题列)

h=$1;next - 如果找到与模式匹配的列,则保存标题值,例如abc.txt变为h并通过next跳过标题

if(NR != 1) {print ""} - 如果它不是标题行首次出现

,则会打印换行符

print h"|"$1; - 使用分隔符和每个下一个后续行打印标题

答案 3 :(得分:1)

awk -F '|' '{if(NF==2)$0=F"|"$0;else{F=$1;$0=""}}NR>1' YourFile

自评:

# use | as separator
awk -F '|' '
  # for every lines
     {
     # line with "data" have 2 field
     if(NF==2) {
        # add File nameand  "|"  in front of current line
        $0 = F"|"$0
        }
      else {
        # File name is field 1
        F=$1
        # change line to empty line
        $0=""
        }
      }
   #print line (in new state, ater 1st line), default action of a trigger
   NR>1  
   ' YourFile