在bash脚本中遍历csv文件中的Array的问题

时间:2014-03-09 22:18:33

标签: arrays linux bash shell csv

所以我在我的代码中尝试做的事情基本上是在具有这种格式的电子表格中阅读

username,   lastname,   firstname,    x1,      x2,       x3,      x4
user1,       dudette,    mary,         7,       2,                 4
user2,       dude,       john,         6,       2,        4,
user3,       dudest,     rad,
user4,       dudaa,      pad,          3,       3,        5,       9

基本上,它具有用户名,用户名对应的名称以及每个x的值。我想要做的是从csv文件中读取,然后找到所有空格并用5s填充它们。我这样做的方法是读入整个数组,然后用0替换所有null空格。到目前为止这是代码......

#!/bin/bash

while IFS=$'\t' read -r -a myarray
do
echo $myarray
done < something.csv

for e in ${myarray[@]
do
echo 'Can you see me #1?'
if [[-z $e]]
echo 'Can you see me #2?'
sed 's//0'
fi
done

代码根本没有真正改变我的csv文件。编辑注意:数据全部以逗号分隔。

到目前为止我已经想到了什么:

好的,'你能看到我'和echo myarray是测试代码。我想看看整个csv文件是否正在从echo myarray读入(根据代码的输出似乎是这种情况)。但是,似乎代码并没有完全通过for循环运行......我似乎无法理解。

非常感谢帮助! :)

3 个答案:

答案 0 :(得分:1)

.csv文件的格式不是以逗号分隔,而是与每个字段之间的非常数空格字符对齐。这使得在尝试查找和替换后面为非空列的空列时很难准确。

以下是仅限Bash的解决方案,如果字段以逗号分隔,则完全准确。

#!/bin/bash

n=5
while IFS=, read username lastname firstname x1 x2 x3 x4; do
    ! [[ $x1 ]] && x1=$n
    ! [[ $x2 ]] && x2=$n
    ! [[ $x3 ]] && x3=$n
    ! [[ $x4 ]] && x4=$n
    echo $username,$lastname,$firstname,$x1,$x2,$x3,$x4
done < something.csv > newfile.csv && mv newfile.csv something.csv

输出:

username,lastname,firstname,x1,x2,x3,x4
user1,dudette,mary,7,2,5,4
user2,dude,john,6,2,4,5
user3,dudest,rad,5,5,5,5
user4,dudaa,pad,3,3,5,9

答案 1 :(得分:0)

我意识到你要求bash,但如果你不介意用perl代替bash,perl是面向记录的文件的一个很好的工具。

#!/usr/bin/perl 
open (FILE, 'something.csv');   
open (OUTFILE, '>outdata.txt'); 
while(<FILE>) {         
        chomp;          
        ($username,$lastname,$firstname,$x1,$x2,$x3,$x4) = split("\t");
        $x1 = 5 if $x1 eq "";
        $x2 = 5 if $x2 eq "";
        $x3 = 5 if $x3 eq "";
        $x4 = 5 if $x4 eq "";
        print OUTFILE "$username\t$lastname\t$x1\t$x2\t$x3\t$x4\n";
}
close (FILE);
close (OUTFILE);
exit;

这将读取您的infile,something.csv,假定它具有制表符分隔的字段,并使用重写的记录写入新文件outdata.txt。

答案 2 :(得分:0)

我确信有一个更好或更惯用的解决方案,但这有效:

#!/bin/bash

infile=bashcsv.csv     # Input filename
declare -i i           # Iteration variable
declare -i defval=5    # Default value for missing cells
declare -i n_cells=7   # Total number of cells per line
declare -i i_start=3   # Starting index for numeric cells
declare -a cells       # Array variable for cells

# We'd usually save/restore the old value of IFS, but there's no need here:
IFS=','

# Convenience function to bail/bug out on error:
bail () {
    echo $@ >&2
    exit 1
}

# Strip whitespace and replace empty cells with `$defval`:
sed -s 's/[[:space:]]//g' $infile | while read -a cells; do

    # Skip empty/malformed lines:
    if [ ${#cells[*]} -lt $i_start ]; then
        continue
    fi

    # If there are fewer cells than $n_cells, pad to $n_cells
    # with $defval; if there are more, bail:
    if [ ${#cells[*]} -lt $n_cells ]; then
        for ((i=${#cells[*]}; $i<$n_cells; i++)); do
            cells[$i]=$defval
        done
    elif [ ${#cells[*]} -gt $n_cells ]; then
        bail "Too many cells."
    fi

    # Replace empty cells with default value:
    for ((i=$i_start; $i<$n_cells; i++)); do
        if [ -z "${cells[$i]}" ]; then
            cells[$i]=$defval
        fi
    done

    # Print out whole line, interpolating commas back in:
    echo "${cells[*]}"
done

这是一个无偿的 awk 单行程,可以完成工作:

awk -F'[[:space:]]*,[[:space:]]*' 'BEGIN{OFS=","} /,/ {NF=7; for(i=4;i<=7;i++) if($i=="") $i=5; print}' infile.csv
相关问题