【问题标题】:Replace column values in a CSV file with awk用 awk 替换 CSV 文件中的列值
【发布时间】:2014-03-05 16:10:13
【问题描述】:

我有这个文件

错误日志

[00:00:00.284],501,

[00:00:00.417],5,5294100071980

[00:00:02.463],501,

[00:00:05.169],501,

[00:00:05.529],501,

[00:00:05.730],501,

所以,如果字段 $3 为空,我想打印“无价值”

我正在尝试这段代码

awk '{{FS=","} if($3=="") {print $1,$2,"No value"}}'

但它会打印出来

>[00:00:00.284] 501 No value
>[00:00:02.463] 501 No value
>[00:00:05.169] 501 No value
>[00:00:05.529] 501 No value
>[00:00:05.730] 501 No value
>[00:00:07.193] 501 No value
>[00:00:09.899] 501 No value
>[00:00:31.312] 501 No value

【问题讨论】:

  • 您的输入文件中的每个真实数据行之间真的有空行吗?

标签: csv text awk compare zero


【解决方案1】:
awk -F ',' -v OFS=',' '$1 { if ($3=="") $3="No value"; print}' in.txt
  • 通过-F 选项传递字段分隔符。
  • 变量OFS,输出字段分隔符,设置为,,因此输出字段也由,分隔。
  • 模式$1确保只处理非空行(即,仅当第一个字段非空时才执行关联的操作)-如果您的输入文件没有空行,您可以删除此模式
  • 如果第三个字段为空,则分配字符串“无值”
  • 最后,输出行(带有可能修改的第三个字段)。

以上是我建议您解决问题的方法,但以下是您原始命令的问题:

  • {{FS=","}... 在您的单个操作中 - 由于没有为每个输入行执行前面的模式 - 您为每一行设置变量 FS - 这不仅没有必要,而且为时已晚 em>,因为那时已经解析了第一行输入(感谢@EdMorton)-要么将其设置在BEGIN 块(BEGIN { FS="," })中,要么如我的回答一样,使用命令行选项@987654331 @ (-F ',')。
  • if($3=="") {...}
    仅当字段 $3 为空时才会产生输出 - 不过,可能您想要输出 all 行,因此使用这种方法,您需要一个 else 分支(打印未修改的行)。
  • print $1,$2,"No value"
    , 字符。这是语法的一部分——它们只是将传递给print的参数分开。给定单独的参数,print 将它们与特殊的 OFS 变量的值连接起来,默认情况下其值为单个 空格;要改用 ,,您必须将其分配给 OFS - 再次,在 BEGIN 块中或通过 -v 选项 (-v OFS=',')。

【讨论】:

  • {FS=","}... [not a problem functionally, but inefficient] 是个问题,因为直到使用默认 FS 将输入文件的第一行拆分为字段后才会执行。
  • 我们可以从发布的输入中看出 $3 可以是数字,我们知道他想在它为空时打印“No value”,但他没有说它不能有数字值 0 所以测试 !$3 与测试“空”不同,那就是 $3 == ""
【解决方案2】:

您应该发布一些预期的输出,但我认为您想要的是:

awk 'BEGIN{FS=OFS=","} NF{print $1, $2, ($3=="" ? "No value" : $3)}' file

【讨论】:

  • +1 表示优雅。 (唯一需要注意的 - 如果需要泛化 - 解决方案仅限于 3 个输出列)。
【解决方案3】:

有了这个文件

cat file
[00:00:00.284],501,
[00:00:00.417],5,5294100071980
[00:00:02.463],501,
[00:00:05.169],501,
[00:00:05.529],501,
[00:00:05.730],501,

awk 应该这样做

awk -F, '$3=="" {$3="No value"}1' OFS=, file
[00:00:00.284],501,No value
[00:00:00.417],5,5294100071980
[00:00:02.463],501,No value
[00:00:05.169],501,No value
[00:00:05.529],501,No value
[00:00:05.730],501,No value

【讨论】:

  • +1 表示简洁;我很好奇您为什么选择伪文件名形式OFS=, 而不是选项形式-v OFS=, - 只是打字方便?语义略有不同,尽管在这种情况下它们的工作方式相同。 (此外,您假设没有空行 - 这可能是一个合理的假设。)
  • 只是为了保存三个字符 :) -v 没有其他原因。
猜你喜欢
  • 1970-01-01
  • 2017-05-20
  • 2016-10-29
  • 2021-07-24
  • 2021-10-14
  • 2013-12-23
  • 1970-01-01
  • 2021-08-26
  • 2014-11-20
相关资源
最近更新 更多