3

我有一个包含许多列的 csv 文件。我正在尝试用同一文件中的倒数第二列替换第二列。例如,如果我有一个文件 sample.csv

1,2,3,4,5,6
a,b,c,d,e,f
g,h,i,j,k,l

我想输出:

1,5,3,4,5,6
a,e,c,d,e,f
g,k,i,j,k,l

谁能帮我完成这项任务?另请注意,之后我将使用 cut 函数丢弃最后两列,因此我愿意将 csv 文件分开,以便我可以将一个 csv 文件中的列替换为另一个 csv 文件中的另一列。哪个更容易实现。提前感谢您的帮助。

4

3 回答 3

11

这个更简单的awk怎么样:

awk 'BEGIN{FS=OFS=","} {$2=$(NF-1)}'1 sample.csv

编辑:注意到您还想丢弃最后两列。使用这个 awk 单行:

awk 'BEGIN{FS=OFS=","} {$2=$(NF-1); NF=NF-2}'1 sample.csv
于 2013-06-28T16:24:30.067 回答
0

在 bash

while IFS=, read -r -a arr; do
  arr[1]="${arr[4]}";  
  printf -v output "%s," "${arr[@]}"; 
  printf "%s\n" "${output%,}"; 
done < sample.csv
于 2013-06-28T16:23:43.867 回答
0

解决方案,IFS以一种有趣的方式使用:

# Set globally the IFS, you'll see it's funny
IFS=,
while read -ra a; do
    a[1]=${a[@]: -2:1}
    echo "${a[*]}"
done < file.csv

全局设置IFS变量被使用两次:一次在read语句中,以便每个字段根据逗号分割,在echo "${a[*]}"where"${a[*]}"将扩展为数组的字段,a由 ... 分隔,IFS这是一个逗号!

另一个特别的事情:您提到倒数第二个字段,这正是${a[@]: -2:1}将扩展到(注意和之间的空间:)的-2内容,因此您不必计算字段数。

警告。csv 文件需要一个难以实现的特殊 csv 解析器。如果字段包含逗号,则此答案(我猜所有其他不使用真正的 csv 解析器的答案)可能会中断,例如,

    1,2,3,4,"a field, with a coma",5

如果要丢弃最后两列,请不要使用cut,而是使用:

IFS=,
while read -ra a; do
    ((${#a[@]}<2)) || continue # skip if array has less than two fields
    a[1]=${a[@]: -2:1}
    echo "${a[*]::${#a[@]}-2}"
done < file.csv
于 2013-06-28T16:32:57.297 回答