如何根据列号无效的控制文件选择列?

如何根据列号无效的控制文件选择列?

我必须根据以下控制文件从源文件动态生成文件。

control_file.txt 
1,3,5,-1,8,-1,4

控制文件包含我从源文件中需要的列的位置。

例如:1列、3列、5列、空白列(-1表示空白列)等等。

我写了一个shell,从控制文件中一一读取位置,生成多个文件。然后最后使用粘贴命令生成新文件,以防我创建触摸文件的-1值。根据文件顺序,通过选项粘贴ls-v

所以我现有的外壳如下所示:

if [ position != -1 ]
then
cut -d, -f$position > file_$var.csv 
else
touch file_$var.csv
fi
paste -d, $(ls -v file_*.csv) > newe_file.csv

我希望有一种方法可以最大限度地减少文件的 I/O,我正在寻找以下内容:

cut -d, -f1,3,5 > file1.csv
touch file2.csv
cut -d, -f8 > file3.csv
touch file4.csv
cut -d, -f4 > file5.csv

或者更好的解决方案会很棒。

源文件中的列数将达到数百列。

预期成绩:

input-file is sample.csv

col1,col2,col3,col4,col5,col6,col7,col8
1,2,3,4,5,6,7,8
9,10,11,12,13,14,15,16

输出.csv:

col1,col3,col5,-1,col8,-1,col4
1,3,5,,8,,4
9,11,13,,16,,12

输出.csv基于controlfile.txt

答案1

另一个答案,比其他答案简单一点:

#!/bin/bash
fields=$(sed -r -e 's/-1/ /g' -e 's/,/ FS /g' \
  -e 's/([0-9]+)/\$\1/g' control_file.txt)
awk -F, "{print ${fields}}" $1

第一个命令转换control_file.txt为合适的awk命令:

$1 FS $3 FS $5 FS FS $8 FS FS $4

运行它:

$ ./script.sh input.csv
col1,col3,col5,,col8,,col4
1,3,5,,8,,4
9,11,13,,16,,12

在你的另一个样本上:

$ ./script.sh sample.csv
BP ID,CurrentMonetary balance ,Provider contract id,,End Date,,charge Plan names 
1100001538,251,00000000000000000141,,18-Oct-12,,[B2] R2 LTE CHARGE PLAN 
1100003404,45.22,00000000000000009349,,23-Nov-13,,B0.3 ECS_CHARGE_PLAN DROP1 V3

答案2

awk 文件

BEGIN { sp="-1" ;  FS="," ; }
FILENAME == "control.txt" { for (i=1;i<=NF;i++) col[i]=$i ;  next ;}
FILENAME != "control.txt" {
    comma="" ;
    for (i=1;i<NF;i++) {
            c=col[i] ;
            if (col[i]!=-1) printf "%s%s",comma,$c ;
            else printf "%s%s",comma,sp ;
            comma="," ;
    }
    printf "\n" ;
    sp="" ;
    }

运行

 awk -f a.awk control.txt  sample.txt
 col1,col3,col5,-1,col8,-1,col4
 1,3,5,,8,,4
 9,11,13,,16,,12

基本上,control.txt 中的第一行获取要打印的列。

答案3

echo '1,2,3,4,5,6,7,8' |
sed 's/[^,]*//7;s///6;s///2;s/,,/,/
    s/\([^,]*\),\([^,]*\),,.*,\(.*\)/\2,,\3,,\1/'

这会删除字段 7、6、2 的内容。接下来,它删除第一个空白字段。然后它交换最后三个非空字段,如 2,,3,,1。

输出

1,3,5,,8,,4

并运行您的示例数据:

BP ID,CurrentMonetary balance ,Provider contract id,,End Date,,charge Plan names 
1100001538,251,00000000000000000141,,18-Oct-12,,[B2] R2 LTE CHARGE PLAN 
1100003404,45.22,00000000000000009349,,23-Nov-13,,B0.3 ECS_CHARGE_PLAN DROP1 V3

话又说回来,只要您可以验证您的分隔符,您就可以只需使用外壳:

set -f; IFS=,
set -- $(cat file; echo "$IFS")
while [ $# -gt 8 ]
do printf %s\\n "$1,$3,$5,,$8,,$4"
   shift "$(($#>7?8:$#))"
done

使用 shell 选项,字段可以包含除分隔符之外的任何内容。只要有分隔符,<space><tab><newline>空字段以外的字段就会被保留。它们包含的任何字符(包括这三个空白字符中的任何一个)都会被保留。这里我用了逗号。您只需要足够的内存来容纳该文件。

相关内容