使用 GNU AWK 处理引用字段中的数据

Posted

技术标签:

【中文标题】使用 GNU AWK 处理引用字段中的数据【英文标题】:Working with data in quoted fields with GNU AWK 【发布时间】:2022-01-19 22:19:54 【问题描述】:

如果之前有人问过这个问题,我深表歉意。我看过但找不到满意的答案。

我有这个示例文件 test.csv:

"abc","def,apple","2019-10-10"

我想根据最后一个字段中的日期输出任何第一个字段。这个我试过了

gawk -vFPAT='[^,]*|"[^"]*"' '($3 >= "2018-10-10") print $1' test.csv

但输出为空。

如果我删除 test.csv 中日期周围的引号,则上述方法有效。该命令输出“abc”。我有一个遵循上述模式的长文件,我确信我可以使用简单的正则表达式来删除日期周围的引号,但是有没有办法通过更改上述 gawk 命令来避免这种情况?

【问题讨论】:

由于您已经在使用 gawk,因此将gensub 添加到条件中以仅在比较中删除引号:(gensub(/^"|"$/,"","g",$3) >= "2019-10-10") 谢谢!这对我有用!我很高兴了解到“gensub”! 【参考方案1】:

$3"2019-10-10",即包含引号,因此您需要在要与之比较的字符串中包含引号:

gawk -v FPAT='[^,]*|"[^"]*"' '($3 >= "\"2018-10-10\"") print $1' test.csv
"abc"

这与仅通过设置 FS 起作用的解决方案之间的区别在于,如果/当您需要对最后一个字段以外的字段进行操作时,即使您的某些字段包含逗号 (,),它也会继续工作或转义引号 ("")。如果您的输入是:尝试所有解决方案:

$ cat test.csv
"abc","very,""bad"",field","2019-10-10","other,""bad"",field."

$ gawk -v FPAT='[^,]*|"[^"]*"' '($3 >= "\"2018-10-10\"") print $1' test.csv
"abc"

您可能真的想将目标日期作为变量传递,所以我是这样写的:

$ gawk -v FPAT='[^,]*|"[^"]*"' -v tgt='"2018-10-10"' '$3 >= tgt print $1' test.csv
"abc"

【讨论】:

谢谢!是的,我真的只是使用了引号转义,而其他所有内容都保持不变,这样我就可以使用除最后一个字段之外的字段。不过,我不知道可以将日期作为变量传递。我将来肯定会使用它。再次感谢!【参考方案2】:

使用 awk:

awk -F ',' '$NF >= "\"2018-10-10\"" print $1 ' test.csv

awk -F '"' '$(NF-1) >= "2018-10-10" print $2 ' test.csv

$NF 包含最后一列

【讨论】:

谢谢!这行得通!看来我只需要知道如何转义引号。我正在使用您的第一个解决方案。 我很抱歉。我将接受的答案更改为另一个,因为它提供了所需的确切答案并且比您的更通用。 (您的仅适用于最后一个字段。)不过,它还是有用的。再次感谢!

以上是关于使用 GNU AWK 处理引用字段中的数据的主要内容,如果未能解决你的问题,请参考以下文章

SELinux系列(十七)—awk命令使用详解

SELinux系列(十七)—awk命令使用详解

文本三剑客之awk

你如何在GNU Awk 4.2中跳过使用FIELDWIDTHS的字符?

Linux文本处理三剑客之GNU awk的使用

Linux文本处理三剑客之GNU awk的使用