Awk 数组中的最后一项未从循环中显示
数组的最后一项无法从循环中正确打印 在学习shell文本过滤器时,我编写了一个小awk脚本,通过提供内联标题来格式化CSV文件的输出 从命令行调用包装器shell脚本,它真正做的就是包装awk脚本,并将参数作为变量Awk 数组中的最后一项未从循环中显示,awk,Awk,数组的最后一项无法从循环中正确打印 在学习shell文本过滤器时,我编写了一个小awk脚本,通过提供内联标题来格式化CSV文件的输出 从命令行调用包装器shell脚本,它真正做的就是包装awk脚本,并将参数作为变量regex传递,该变量是搜索字符串 脚本将第一条记录的字段(NR==1)存储到数组标题中。一旦在CSV文件正文中找到包含搜索字符串regex的记录,脚本就会将标题连接到适当的值 csv.sh: #/bin/bash awk-f~/Scripts/csv.awk-v“regex=$1”$
regex
传递,该变量是搜索字符串
脚本将第一条记录的字段(NR==1
)存储到数组标题中。一旦在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("")
}
}
调用
$csv Enterprise ships.csv
预期产量
终端输出:
在我的Linux计算机(Manjaro)上,输出非常相似。但实际上,如果我在Mac上通过管道将输出传输到pbcopy
,粘贴后标题确实会显示出来:
name: USS Enterprise
country: United States of America
displacement: 19800
length: 251.4
beam: 33.4
commissioned
: 12 May 1938
将数组传递给length
函数是无效的
如果您怀疑某个混乱的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("")
}
}
测试
$ ./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
如果你的标题被篡改了,所以他们没有,比如说,委托的列,这也会在那个场景中无缝地工作
测试
$ ./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
根据格伦的评论,你能试试下面的吗
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
awk'开始{FS=“,”;}
{gsub(/\r/,“”)}
NR==1{
对于(i=1;i1{
如果($0~regex){
对于(i=1;i0){
打印(标题[i]:“$i)
}
}
打印(“”)
}
}'输入文件
I您的数据文件有DOS样式的\r\n
行尾。单词“committeed”实际上是committeed\r
,因此光标被发送到冒号之前的行首并打印值。Glenn如果长度(标题),我不能投票支持您的注释
不等于NF
那么您就有问题了,因此iI不希望循环在没有要连接的头的情况下产生格式化输出。因此,如果它是一个混乱的CSV文件,其中只提供了3个头,但数据有5列……但是awk的长度函数似乎能够理解上下文并给出正确的输出f或者数组长度。@JasperZanjani我修改了答案以反映评论中提到的问题。
$ ./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
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