【问题标题】:how to skip blank space if value is not there and print proper row and column如果值不存在如何跳过空格并打印正确的行和列
【发布时间】:2021-03-24 20:08:10
【问题描述】:

我有一个 details.txt 文件,其中包含以下数据

size=190000
date=1603278566981
repo-name=testupload
repo-path=/home/test/testupload
size=140000
date=1603278566981
repo-name=testupload2
repo-path=/home/test/testupload2
size=170000
date=1603278566981
repo-name=testupload3
repo-path=/home/test/testupload3

以及下面的awk脚本进程

#!/bin/bash
awk -vOFS='\t' '
BEGIN{ FS="=" }
/^size/{
  if(++count1==1){ header=$1"," }
  sizeArr[++count]=$NF
  next
}
/^@repo-name/{
  if(++count2==1){ header=header OFS $1"," }
  repoNameArr[count]=$NF
  next
}
/^date/{
  if(++count3==1){ header=header OFS $1"," }
  dateArr[count]=$NF
  next
  }
/^@blob-name/{
  if(++count4==1){ header=header OFS $1"," }
  repopathArr[count]=$NF
  next
}
END{
  print header
  for(i=1;i<=count;i++){
    printf("%s,%s,%s,%s,%s\n",sizeArr[i],repoNameArr[i],dateArr[i],repopathArr[i])
  }
}
' details.txt | tr -d @ |awk -F, '{$3=substr($3,0,10)}1' OFS=,|sed 's/date/creationTime/g'

按预期打印值,(因为它有 reponame)

size    "   repo-name"  "   creationTime"   "   blob-name"
10496000    testupload  Fri 11 Dec 2020 07:35:56 AM CET testfile.tar11.gz
10496000    testupload  Thu 10 Dec 2020 02:44:04 PM CET testfile.tar.gz
9602303     testupload  Fri 11 Dec 2020 07:38:58 AM CET apache-maven-3.6.3-bin/apache-maven-3.6.3-bin.zip

但是当文件的文件格式中缺少某些内容时,格式错误(这里 repo 名称跳转到最后一列的标题,因为前几个数据没有 reponame 值)

size    "   creationTimeime"    "   blob-name"  "       "   repo-name"
261304      Thu 13 Feb 2020 08:50:02 AM CET temp    8963d25231b
29639       Thu 13 Feb 2020 08:50:00 AM CET temp    3780c72cab5
93699       Thu 13 Feb 2020 08:50:00 AM CET temp    209276c91ba

并且列标题打印错误但数据打印完美,是否有任何东西可以验证是否其中一个字段不存在,它应该跳过该字段并以正确的格式打印其余部分。

如果数据不可用,则应保持该标头相同,而不应标头序列。

我的要求 如果 deatils.txt 缺少任何记录,则应跳过该记录并打印为空白并按标题打印。 如果 repo-name 字段不存在,但其余输出正确,则 headers 会受到干扰,因此即使字段丢失,我们也需要保持 headers 完整。

错误: 大小 "creationTimeime" "blob-name" ""repo-name" 261304 2020 年 2 月 13 日星期四 08:50:02 AM CET 温度 8963d25231b 29639 2020 年 2 月 13 日星期四 08:50:00 AM CET 温度 3780c72cab5 93699 Thu 13 Feb 2020 08:50:00 AM CET temp 209276c91ba

size    "   repo-name"  "   creationTime"   "   blob-name"
    10496000    testupload  Fri 11 Dec 2020 07:35:56 AM CET testfile.tar11.gz
    10496000    testupload  Thu 10 Dec 2020 02:44:04 PM CET testfile.tar.gz
    9602303     testupload  Fri 11 Dec 2020 07:38:58 AM CET apache-maven-3.6.3-bin/apache-maven-3.6.3-bin.zip

谢谢

武士

【问题讨论】:

  • 很好,你已经在你的问题中发布了你的努力,继续努力。您能否以文本形式在您的问题中发布预期输出示例,不鼓励使用图片或链接,谢谢。
  • @RavinderSingh13 added images ,如果 reponame 不存在它会干扰标题对齐 ii 尝试使用 sed 检查但没有运气。如果数据不存在,我们是否可以为某些行打印空白并按预期打印下一个所有详细信息,请您指导一下,reponame 值将可供所有人使用,但很少有它不存在,这就是标题对齐错误的地方。
  • @Samurai :/^@repo-name/ 中的@ 是什么意思? awk-regexp 的一些特殊功能?我找不到任何解释。
  • @user1934428 不,这是试图匹配的文字 @(与发布的输入不匹配)。没有理由认为这个任务在 perl 或 ruby​​ 或任何其他工具中比在 awk 中更容易 - 这正是 awk 旨在解决的问题。
  • @Samurai 您发布的脚本不会从您发布的输入中产生您所说的输出,并且实际输出和您发布的预期输出都不能从您发布的输入中生成(不同值)所以你让我们很难帮助你。请edit您的问题至少显示简洁、可测试的样本输入以及您在给定该输入的情况下期望的输出。还要说明您输入中的任何字段是否保证始终存在(与 repo-name 不同),或者是否有其他方法可以确定何时完全读取每条记录。

标签: linux shell csv awk sed


【解决方案1】:

你可以试试这个gnu awk:

awk -F= -v OFS='\t' 'function prt(ind, name, s) {s=map[ind][name]; return (s==""?" ":s);} {map[NR][$1] = $2} END {print "Size", "Repo Name", "CreationTime", "Repo Path"; for (i=1; i<=NR; i+=4) print prt(i, "size"), prt(i+2, "repo-name"), prt(i+1, "date"), prt(i+3, "repo-path")}' file

Size    Repo Name    CreationTime   Repo Path
190000  testupload   1603278566981  /home/test/testupload
140000  testupload2  1603278566981  /home/test/testupload2
170000  testupload3  1603278566981  /home/test/testupload3

使其可读:

awk -F= -v OFS='\t' 'function prt(ind, name, s) {
   s = map[ind][name]
   return (s==""?" ":s)
}
{
   map[NR][$1] = $2
}
END {
   print "Size", "Repo Name", "CreationTime", "Repo Path"
   for (i=1; i<=NR; i+=4)
      print prt(i, "size"), prt(i+2, "repo-name"), prt(i+1, "date"), prt(i+3, "repo-path")
}' file 

【讨论】:

  • 谢谢,但我们没有在操作系统上安装 column 命令,这限制了我们获得期望的输出,我们可以使用任何替代方法来代替 column
  • 你能告诉我如何执行这个吗,当我尝试 awk -F= -v OFS='\t' 'function prt(ind , 名称, s) {s=map[ind][name]; return (s==""?" ":s);} {map[NR][$1] = $2} END {print "Size", "Repo Name", "CreationTime", "Repo Path"; for (i=1; i
  • 请查看此在线演示:ideone.com/EIwom6
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-13
  • 1970-01-01
  • 2021-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
相关资源
最近更新 更多