列番号が正しくない制御ファイルに基づいて列を選択するには?

列番号が正しくない制御ファイルに基づいて列を選択するには?

次の制御ファイルに基づいてソースファイルからファイルを動的に生成する必要があります。

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

制御ファイルには、ソースファイル内の必要な列の場所が含まれています。

例:1列、3列、5列、空欄(-1は空欄を意味)など

制御ファイルから場所を1つずつ読み取り、複数のファイルを生成するシェルを作成しました。次に、-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など、空でない最後の3つのフィールドを置き換えます。

出力

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

シェルオプションを使用すると、フィールドに区切り文字を除くすべての項目を含めることができます。区切り文字がある限り、空のフィールド<space><tab><newline>以外のフィールドは保持されます。 3つの空白文字を含むすべての文字は保持されます。ここではカンマを使用しました。ファイルを保持するのに十分なメモリが必要です。

関連情報