循环中未显示数组中的最后一项

时间:2019-04-15 18:12:01

标签: awk

数组的最后一项在循环中无法正确打印

在学习shell文本过滤器时,我制作了一个awk脚本,该脚本通过提供标题内联来格式化CSV文件的输出。

从命令行调用包装程序外壳脚本,而它真正要做的只是包装awk脚本并传递一个作为变量regex的参数,它是搜索字符串。

该脚本将第一条记录(NR==1)的字段存储到数组heading中。在CSV文件的正文中找到包含搜索字符串regex的记录后,脚本会将标题连接到适当的值。

csv.sh:

#!/bin/bash

awk -f ~/Scripts/csv.awk -v "regex=$1" $2

csv.awk:

BEGIN {FS=",";}
NR==1 { 
  for (i=1; i<=NF; i++) { 
    heading[i]=$i; 
  } 
}
NR>1 {
  if ($0 ~ regex) {
    for (i=1; i<=length(heading); i++) {
      if(length($i) > 0) { 
        print(heading[i] ": " $i)
      } 
    }
    print("")
  }
}

演示

ships.csv:

name,country,displacement,length,beam,commissioned
Yamato,Japan,65027,256,38.9,16 December 1941
USS Enterprise,United States of America,19800,251.4,33.4,12 May 1938
Bismarck,Germany,41700,251,36,24 August 1940
HMS Dreadnought,United Kingdom,18120,160.6,25,2 December 1906
USS Iowa,United States of America,46000,270.43,32.97,22 February 1943
HMS Vanguard,United Kingdom,45200,248.2,32.9,12 May 1946

调用

$ csv Enterprise ships.csv

预期输出

name: USS Enterprise
country: United States of America
displacement: 19800
length: 251.4
beam: 33.4
commissioned: 12 May 1938

端子输出:

name: USS Enterprise
country: United States of America
displacement: 19800
length: 251.4
beam: 33.4
: 12 May 1938

在我的Linux计算机(Manjaro)上,输出非常相似。但是实际上,如果我将输出通过管道传输到Mac上的pbcopy,则在粘贴后确实会显示标题:

name: USS Enterprise
country: United States of America
displacement: 19800
length: 251.4
beam: 33.4
commissioned
: 12 May 1938

2 个答案:

答案 0 :(得分:1)

根据格伦的评论,您能不能试一下。

awk 'BEGIN {FS=",";}
{gsub(/\r/,"")}
NR==1 { 
  for (i=1; i<=NF; i++) { 
    heading[i]=$i; 
  } 
}
NR>1 {
  if ($0 ~ regex) {
    for (i=1; i<=length(heading); i++) {
      if(length($i) > 0) { 
        print(heading[i] ": " $i)
      } 
    }
    print("")
  }
}'  Input_file

答案 1 :(得分:0)

将数组传递给length函数是less portable

如果您怀疑标题文件可能与实际列不匹配的csv文件杂乱无章,那么一种可移植的方法是将总列数存储在开头,然后像下面这样重复使用:

NR==1 { 
  headercount=NF; # store the count
  for (i=1; i<=NF; i++) { 
    heading[i]=$i; 
  } 
}
NR>1 {
  if ($0 ~ regex) {
    for (i=1; i<=headercount; i++) { #Use the count
      if(length($i) > 0) {
        print(heading[i] ": " $i)
      }
    }
    print("")
  }
}

此外,如果您必须处理dos样式的文件结尾,则可以将脚本更改为:

#!/bin/bash
dos2unix -q "$2" # This makes sure that the input file has unix style file endings
awk -f ./csv.awk -v "regex=$1" $2

测试

$ ./csv.sh HMS ships.csv 
name: HMS Dreadnought
country: United Kingdom
displacement: 18120
length: 160.6
beam: 25
commissioned: 2 December 1906

name: HMS Vanguard
country: United Kingdom
displacement: 45200
length: 248.2
beam: 32.9
commissioned: 12 May 1946

如果您的标题被篡改,以致它们没有委托列,那么在这种情况下,它也可以无缝地工作。

测试

$ ./csv.sh HMS ships.csv 
name: HMS Dreadnought
country: United Kingdom
displacement: 18120
length: 160.6
beam: 25

name: HMS Vanguard
country: United Kingdom
displacement: 45200
length: 248.2
beam: 32.9