如何使用 bash/shell 命令根据不同列上的匹配值从 csv 文件中的列返回值

如何使用 bash/shell 命令根据不同列上的匹配值从 csv 文件中的列返回值

我需要有关执行以下操作的 bash 脚本的帮助:

| section | category | description | date      | metric | value    |
| --------| ---------|-------------|-----------|--------|----------|
| y       | testing  |    abc      |03/02/2022 |        |  14845.0 |
| x       | row      |    pqy      | 01/16/2022|        | 12565.0  |
| x       | row      |    xyz      | 02/21/2021|        | 13888.0  |
| x       | row      |    xyz      | 10/04/2020|        | 18160.0  |

当我搜索它的描述时,我想按降序返回值列以及日期,xyz应该只返回与该值相对应的值,并且只返回与一个日期相关的最高值。也可能有重复的日期。例如:

10/04/2020 18160
02/21/2021 13888 

在上面的例子中,我有描述,xyz并且它返回按降序排列的值以及日期。

我尝试过的:我一直坚持这个

awk '$2 ~ /xyz/ {print $3}' covid19_cases_demographics_tests_2022-03-21.csv(this is my csv file)

请通过一些示例来指导我正确的方向,因为我是 shell 脚本和 unix 东西的新手。谢谢

答案1

根据您显示的列,您在中使用了错误的索引awk

看起来您假设第一列(部分)将是$0,第二列(类别)将是$1,第三列(描述)将是$2。但awk实际上用来$0表示整条线。因此,要在描述列上搜索,您需要$3在匹配逻辑中使用并$6从值列中打印。假设您有正确的 csv 文件(不是其他格式),您可能还需要设置 -F 选项来指定自定义字段分隔符,例如逗号。但请注意,这有一个问题,即包含带引号的字符串的更复杂的 csv 文件可能仍然会破坏这个问题。

awk -F, '$3 ~ /xyz/ {print $6}' file.csv

如果您有更复杂的 csv 文件,其中引用的字符串可能包含空格甚至逗号等不用作分隔符的字符串,那么awk(以及grepsed) 可能不是完成这项工作的最佳工具。在这种情况下,该csvtool实用程序是上下文感知的并且应该工作得更好。在 Fedora 上,该实用程序是软件包的一部分ocaml-csv,但该软件包在其他发行版上的名称可能有所不同。

在这种情况下,您可以编写一个函数来打印所需的列,导出该函数,然后将csvtool列传递给它。如果您有更复杂的字段,则需要更多工作,但更安全。

function printifcol {
    local descCol="$3";
    local valueCol="$6";
    if [[ "xyz" == "${descCol}" ]]; then
        echo "${valueCol}";                               
    fi                       
}
export -f printifcol;
csvtool call printifcol file.csv

在任何一种情况下,您都可以使用(反向)选项将输出sort通过管道传输到命令-r,以按降序排列:

awk -F, '$3 ~ /xyz/ {print $6}' file.csv | sort -r
 
# assumes function was already exported
csvtool call printifcol file.csv | sort -r

相关内容