如何将值从一列复制到另一列?

时间:2019-04-23 01:27:58

标签: linux bash shell csv awk

我有带有两个价格列的CSV数据。如果$ 4列中存在一个值,我想将其复制到同一行的$ 3列中。如果$ 4为空,则应保留$ 3。

这些都不起作用:

awk -F',' '{ if (length($4) == 0) $3=$4 }'
awk -F',' '{ if(!length($4) == 0 ) print $4 }'

这将输出带有样本表的每一行

awk -F',' '{ if(!length($4) == 0 ) print $0 }' inputfile

这将不输出任何样品表

awk -F',' '{ if(length($4) == 0 ) print $3 }' inputfile

我已经清理了两个输入文件,修复了标题行,并使用sed,awk,sort和join将它们加入。现在剩下的就是一个看起来像这样的CSV文件:

itemnumber,available,regprice,mapprice
00061,9,19.30,
00061030,31,2.87,3.19
00062,9,15.44,
00062410,2,3.59,3.99
00064,9,15.44,
00066850,29,2.87,3.99
00066871,49,4.19,5.99
00066878,3,5.63,7.99

如果同一行中的$ 4列具有值,我需要覆盖$ 3列。最终结果将是:

itemnumber,available,regprice,mapprice
00061,9,19.30,
00061030,31,3.19,3.19
00062,9,15.44,
00062410,2,3.99,3.99
00064,9,15.44,
00066850,29,3.99,3.99
00066871,49,5.99,5.99
00066878,3,7.99,7.99

4 个答案:

答案 0 :(得分:2)

$ awk 'BEGIN{FS=OFS=","} (NR>1) && ($4!=""){$3=$4} 1' file
itemnumber,available,regprice,mapprice
00061,9,19.30,
00061030,31,3.19,3.19
00062,9,15.44,
00062410,2,3.99,3.99
00064,9,15.44,
00066850,29,3.99,3.99
00066871,49,5.99,5.99
00066878,3,7.99,7.99

答案 1 :(得分:1)

让我们看看您尝试过的所有事情:

  1. awk -F',' '{ if (length($4) == 0) $3=$4 }'

    这表明,如果字段4的长度为零,则将字段3设置为等于字段4。您不要求awk打印任何内容,因此它将不执行任何操作。这样可以打印出一些内容:

    awk -F',' '{ if (length($4) == 0) $3=$4 }{print $0}'
    

    但是在所有字段分隔符都等于一个空格的情况下,您应该这样做:

    awk 'BEGIN{FS=OFS=","}{ if (length($4) == 0) $3=$4 }{print $0}'
    
  2. awk -F',' '{ if(!length($4) == 0 ) print $4 }'

    在此说明,如果字段4的长度等于零,则不为true,则打印字段4。 正如您提到的那样,什么都没有打印出来,它很可能表明您在字段4中隐藏了字符,例如CR(请参阅:Remove carriage return in Unix),甚至只有空格。您可以尝试类似

    awk -F',' '{sub(/ *\r?$/,""){ if(!length($4) == 0 ) print $4 }'`**
    
  3. awk -F',' '{ if(!length($4) == 0 ) print $0 }' inputfile

    请参阅2

  4. awk -F',' '{ if(length($4) == 0 ) print $3 }' inputfile

    这证实了我对2的怀疑

我对您问题的解决方案将基于2的建议和Ed Morton的解决方案。

awk 'BEGIN{FS=OFS=","} {sub(/ *\r?/,"")}(NR>1) && ($4!=""){$3=$4} 1' file

答案 2 :(得分:0)

以下是与您的结果匹配的代码:

awk -F, -v OFS=, '
  NR == 1 
  NR >  1 { 
    if ( $4 == "" ) 
      print $1,$2,$3,$4 
    else 
      print $1,$2,$4,$4 } 
' $*

过去,我遇到了像$ 3 = $ 4这样的表达式,所以我只打印了所有字段。

编辑:埃德·莫顿(Ed Morton)为避免不进行故障排除而避免$ 3 = $ 4感到羞耻。我在下面给了它另一张照片:

awk -F, -v OFS=, '
  NR == 1 
  NR >  1 { 
    if ( $4 != "" ) 
      $3 = $4
    print 
  }
' $*

以上实现相同的结果。

答案 3 :(得分:0)

在gnu awk上尝试

awk -F, -vOFS=, '/[0-9.]+/{if($4)$3=$4} {print}' file