在Bash

时间:2017-05-25 09:39:39

标签: bash csv awk

我遇到客户需要复制CSV文件中的列的问题。这些值总是相同的,不幸的是我们的API不允许在JSON中指定重复的列。

例如,我有以下列结构和值:

Name, Surname, City, Age, Job
John, Doe, Johannesburg, 28, Technical Support

现在我需要复制City,因此输出应为:

Name, Surname, City, City Again, Age, Job
John, Doe, Johannesburg, Johannesburg, 28, Technical Support

该列需要放在那个将被复制的列之后。该值也取决于第一列。

4 个答案:

答案 0 :(得分:5)

awk可以轻松应对:

awk 'BEGIN{FS=OFS=", "} {$3 = $3 OFS $3} 1' file.csv

Name, Surname, City, City, Age, Job
John, Doe, Johannesburg, Johannesburg, 28, Technical Support

请注意,这可以在单个和短路命令中完​​成这项工作,该命令易于阅读,并且比管道命令更有效,包括调用cut两次然后“粘贴”。

正如@codeforester在下面正确评论的那样,cut不允许在输出中重复列;它用于剥离值。

答案 1 :(得分:0)

假设City始终位于第3列,可以使用cutpaste命令。例如:

csv=path/to/somefile.csv
echo "$(paste -d',' <(cut -d',' -f1-3 $csv) <(cut -d',' -f3- $csv))" > "$csv"

注意:

  1. 分配给path/to/quux.csv变量的csv部分应替换为.csv文件的实际路径。
  2. 包含重复的City列的新内容将写回同一源文件。
  3. <(...)部分称为流程替换,通常在无法使用管道数据时使用。可以找到对它的一个很好的解释here

答案 2 :(得分:0)

前段时间,我写了一个bash函数来插入数组元素:

function array_insert {
    # options: arrayname index [value]
    if ! declare -p "$1" 2>/dev/null | grep -q '^declare -a'; then
        printf '%s: not an array: %s\n' "$0" "$1" >&2
        return 1
    fi
    local -n source="$1"
    local -a indices=( "${!source[@]}" )
    for ((i=${#indices[@]}-1; i>=$2; i--)) ; do
        source[$((i+1))]="${source[$i]}"
    done
    if [ -n "$3" ]; then
        source[$2]="$3"
    fi
}

加载此功能后,您可以执行以下操作:

while read line; do
  IFS=, declare a=( $line )     # assign the line's fields to an array,
  array_insert a 3 "${a[2]}"    # insert the column in this line,
  o=$(printf '%s,' "${a[@]}")   # assemble your output,
  printf '%s\n' "${o%,}"        # remove the trailing comma.
done < input.txt

对我来说,这会使用您的输入提供以下输出:

Name, Surname, City, City, Age, Job
John, Doe, Johannesburg, Johannesburg, 28, Technical Support

请注意,在bash中,数组是从0建立索引的,因此${a[2]}是第三列。

答案 3 :(得分:0)

下面是小脚本,它有两个输入

  1. 文件名
  2. 列名 它将重复提及列
  3. 以下是脚本

    echo "Enter  CSV File  name "
    read fileName
    
    echo "Enter Column name to be duplicated "
    read columnName
    
    
    columnNumber=`head -1 $fileName | awk -v RS="," "/$columnName/{print NR;}"`     #Identify Column number using column name
    totalNumberOfColumn=`head -1 $fileName | awk -F',' '{print NF}'`                #identify total number of column
    
    str=""                                                                          #Create empty variab str to print column number in awk
    for ((i=1;i<=$totalNumberOfColumn;i++));
    do
    str="$str \$$i\",\""
            if [ $i == $columnNumber ]
            then
            str="$str \$$i\",\""
            fi
    done
    
    
    awk -F',' "{print ${str}}" $fileName  | sed 's/,$//g'                           #Print all column inculding duplicate column 
    

    下面是文件内容,文件名是 data.csv

    :cat data.csv
    Name, Surname, City, Age, Job
    John, Doe, Johannesburg, 28, Technical Support
    

    复制列城市

    的输出1
    :bash script.sh
    Enter  CSV File  name
    data.csv
    Enter Column name to be duplicated
    City
    Name, Surname, City, City, Age, Job
    John, Doe, Johannesburg, Johannesburg, 28, Technical Support
    

    输出2:用于复制列名称

    :bash script.sh
    Enter  CSV File  name
    data.csv
    Enter Column name to be duplicated
    Name
    Name,Name, Surname, City, Age, Job
    John,John, Doe, Johannesburg, 28, Technical Support