【问题标题】:How to replace multiple columns in CSV file using AWK or SED?如何使用 AWK 或 SED 替换 CSV 文件中的多个列?
【发布时间】:2021-07-24 10:06:19
【问题描述】:

我想用文件中的一些键替换一行中的列

for val in "${keyarr[@]}";
do
    while read dataline <&3 && read keyline <&4; do
        echo $dataline |
        awk -F $ifs -v col=$val -v line=$keyline '{
            $col=line; print $0 ;} ' OFS=$ifs > sourcedata1
    done 3<sourcedata1 4<keysnotfound
done

val 是我想用键替换的列号。

所以我可能要替换多个列。

此解决方案不起作用。 如何一次用键替换多个列。

例如我从sourcedata1获取一行

101, 102, 103 , 104

在while循环中来自keynotfound

105

在for循环的第一次迭代val = 1

然后我想用键替换数据行的第一列

105, 102, 103, 104

如果val = 3,第二次迭代也一样。

105, 102, 105, 104

我想要一个 AWK 或 SED 本身的解决方案,而不是使用 for 循环,它应该使用多列中的键更新源文件。

【问题讨论】:

  • 眼前的问题可能是因为incorrect (lack of) quoting;但是重复循环遍历相同的两个文件似乎非常低效和不优雅。 keyarr 中有什么内容?所有这些可能都应该重构为一个单独的 Awk 脚本,但是如果没有看到输入数据,就很难确切地说出是如何做到的。
  • 是的,我发现并纠正了它,但仍然需要一个解决方案来更新同一行中的所有键。

标签: linux awk sed


【解决方案1】:

您的问题陈述相当模糊,但我猜像这样的重构应该可以满足您的要求。

无需循环遍历相同的文件并重写其中一个,只需传入列索引数组,然后读取文件一次。

cols=$(printf '%s;' "${keyarr[@]}")
awk -F "$ifs" -v c="${cols%;}" 'BEGIN { split(c, cols, ";"); OFS=IFS }
    NR==FNR { repl[FNR] = $0; next }
    { for(col in cols) $col = repl[FNR] }' keysnotfound sourcedata1

Awk 习惯用法NR==FNR { ...; next } 是将第一个输入文件读入内存的常用方法(因为整个输入行号NR 等于当前文件中的行号FNR)。我们将keysnotfound 中的条目读入repl,它由行号索引。有了这个,我们可以遍历并处理第二个文件,我们在其中循环列索引,并将每个索引替换为我们从第一个文件中为该行号收集的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-17
    • 2011-01-23
    • 2018-07-02
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-20
    相关资源
    最近更新 更多