CSVファイルから列を削除するコマンドライン注文がありますか?

CSVファイルから列を削除するコマンドライン注文がありますか?

次の内容を含むファイル:

1111,2222,3333,4444
aaaa,bbbb,cccc,dddd

元と同じですが、n番目の列(たとえば、n = 2(または3))が見つからないファイルを取得しようとしています。

1111,2222,4444
aaaa,bbbb,dddd

またはn = 0の場合(または1の場合があります)

2222,3333,4444
bbbb,cccc,dddd

実際のファイルの長さはギガバイトに達し、数万列を含めることができます。

この場合、いつものように、コマンドラインの魔術師がエレガントなソリューションを提供できると考えられます... :-)

実際の場合は、最初の列を2つ削除する必要がありますが、最初の列を順番に2回削除するだけですが、一般化する方が面白いと思いました。

答え1

私はこれがGNU coreutilsに固有のものだと思います。

$ cut --complement -f 3 -d, inputfile
1111,2222,4444
aaaa,bbbb,dddd

通常、-fで必須フィールドを指定しますが、--complementを追加すると自然に意味を変えることができます。 「人杀」から:

--complement
    complement the set of selected bytes, characters or fields

1つの注意点:列にカンマが含まれていると、cutがスプレッドシートと同じCSVパーサーではないため、cutoffが発生します。多くのパーサーは、CSVでエスケープされたコンマを処理する方法についてさまざまな考えを持っています。単純なCSVの場合は、コマンドラインでまだcutを使用する方法を使用します。

答え2

データがカンマ区切りの列のみで構成されている場合:

cut -d , -f 1-2,4-

awkを使用することもできますが、フィールドを消去するのは簡単ですが、区切り文字を削除するには少し作業が必要なため、少し厄介です。空のフィールドがなければそれほど悪くはありません。

awk -F , 'BEGIN {OFS=FS}  {$3=""; sub(",,", ","); print}'

正しく引用されている場合、フィールド内にカンマが表示される可能性がある実際のCSVがある場合は、次のものが必要です。実際のCSVライブラリ

答え3

CSV認識ツールを使用して、タイトルなしのCSV入力ファイルから最初の2つの列を削除します。

$ cat file
1111,2222,3333,4444
aaaa,bbbb,cccc,dddd
$ mlr --csv -N cut -x -f 1,2 file
3333,4444
cccc,dddd

-x作業オプションcutミラーmlr)は操作を実行します。入らないようにするフィールド名を指定します(この場合はフィールド番号1と2)。 CSVデータにヘッダーがある場合は、名前付きフィールドを使用できます-f-Nこの場合はこのオプションも削除する必要があります)。

MillerはCSVをサポートしているため、挿入されたカンマ、引用符、および改行を含む引用符フィールドを正しく処理できます。

答え4

インデックスを使用する列を削除するには、次のコマンドを試してください。

dropColumnCSV --index=0 --file=file.csv

列が以下のようにコンマで区切られている場合は機能します。sed関数内で文字列を削除するコマンドが使用されます。

dropColumnCSV() {
  # argument check
  while [ $# -gt 0 ]; do
    case "$1" in
      --index=*)
        index="${1#*=}"
        ;;
      --file=*)
        file="${1#*=}"
        ;;
      *)
        printf "* Error: Invalid argument. *\n"
        return
    esac
    shift
  done

  # file check
  if [ ! -f $file ]; then
        printf "* Error: $file not found.*\n"
        return
  fi

  # sed remove command index zero
  if [[ $index == 0 ]]; then
    sed -i 's/\([^,]*\),\(.*\)/\2/' $file

  # sed remove command index greater than zero
  elif [[ $index > 0 ]]; then
    pos_str=$(for i in {1..$(seq "$index")}; do echo -n '[^,]*',; done| sed 's/,$//') ;
    sed -i 's/^\('$pos_str'\),[^,]*/\1/' $file
  fi
}

関連情報