Shell 迭代读取 CSV 文件为变量赋值

2023-12-25 19:48:34

有时候,我们可能需要在 Shell 中维护一个KV结构的数组,也就是类似于 List<Map<String,Stirng>>这样的数据结构,但是这在 Shell 中并不容易实现,一些联合使用 Shell 的 Indexed Arrays 和 Associative Arrays 进行模拟的方案虽然可行,但其实使用起来还是很别扭的,此时,最自然做法是把这些值抽离到单独的 CSV 文件中维护,然后用 Shell 循环读取每一行并对变量进行赋值。这里插一句题外话,这个需求使用 Json 文件同样可以实现,配合强大的 jq 命令可以轻松提取各种复杂的嵌套结构。不过这里的数据结构非常简单,使用 csv 储存和读写都会简洁许多,两种风格可以视需求和个人喜好自定定夺。

我们以这样一个 CSV 文件为例:

containers-per-node,map-mem,map-vcores,reduce-mem,reduce-vcores,am-mem,am-vcores,mappers
4,15360,8,15360,8,15360,8,127
8,7680,4,7680,4,7680,4,255
12,5120,3,5120,4,5120,4,383
16,3840,2,7680,4,7680,4,510

下面的 Shell 脚本演示了如何读取每一行内容,并将相应的字段赋值给对应变量:

IFS=,
row=0
cat above-csv-file.csv | while read -r CONTAINERS_PER_NODE MAP_MEM MAP_VCORES REDUCE_MEM REDUCE_VCORES AM_MEM AM_VCORES MAPPERS; do
    # skip first header line
    if [[ $row -eq 0 ]]; then
        row=$((row+1))
        continue
    fi
    echo "mapreduce.map.memory.mb = $MAP_MEM"
    echo "mapreduce.map.cpu.vcores = $MAP_VCORES"
    echo "mapreduce.reduce.memory.mb = $REDUCE_MEM"
    echo "mapreduce.reduce.cpu.vcores = $REDUCE_VCORES"
    echo "yarn.app.mapreduce.am.resource.mb = $AM_MEM"
    echo "yarn.app.mapreduce.am.resource.cpu-vcores = $AM_VCORES"
    echo "total containers per node: $CONTAINERS_PER_NODE"
    echo "total containers for map: $MAPPERS"
    row=$((row + 1))
done

特别地,有时候我们很希望能添加一行CSV就自动执行一次,而不是从头开始执行CSV提供的配置,这在测试时非常有用。此时,我们可以使用 tail -F -n +1 xxx.csv 的形式去替换 cat xxx.csv,这将赋予脚本持续关注文件最后一行变化的能力,一但有更新,立即执行:

IFS=,
row=0
tail -F -n +1 above-csv-file.csv | while read -r CONTAINERS_PER_NODE MAP_MEM MAP_VCORES REDUCE_MEM REDUCE_VCORES AM_MEM AM_VCORES MAPPERS; do
    # skip first header line
    if [[ $row -eq 0 ]]; then
        row=$((row+1))
        continue
    fi
    echo "mapreduce.map.memory.mb = $MAP_MEM"
    echo "mapreduce.map.cpu.vcores = $MAP_VCORES"
    echo "mapreduce.reduce.memory.mb = $REDUCE_MEM"
    echo "mapreduce.reduce.cpu.vcores = $REDUCE_VCORES"
    echo "yarn.app.mapreduce.am.resource.mb = $AM_MEM"
    echo "yarn.app.mapreduce.am.resource.cpu-vcores = $AM_VCORES"
    echo "total containers per node: $CONTAINERS_PER_NODE"
    echo "total containers for map: $MAPPERS"
    row=$((row + 1))
done

提醒注意的是:上述脚本不会主动退出,如果是在后台运行,需要 kill 掉相关进程。

文章来源:https://blog.csdn.net/bluishglc/article/details/135204496
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。