Gibt es einen Befehlszeilenbefehl zum Löschen einer Spalte in einer CSV-Datei?

Gibt es einen Befehlszeilenbefehl zum Löschen einer Spalte in einer CSV-Datei?

Sie haben eine Datei mit folgendem Inhalt:

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

Ich möchte eine Datei erhalten, die dem Original entspricht, in der aber eine n-te Spalte fehlt, z. B. für n = 2 (oder kann es auch 3 sein)

1111,2222,4444
aaaa,bbbb,dddd

oder für n = 0 (oder kann es auch 1 sein)

2222,3333,4444
bbbb,cccc,dddd

Eine echte Datei kann mehrere Gigabyte groß sein und Zehntausende Spalten haben.

Wie immer in solchen Fällen vermute ich, dass Kommandozeilen-Zauberer eine elegante Lösung anbieten können … :-)

In meinem tatsächlichen realen Fall muss ich zwei erste Spalten löschen, was dadurch erreicht werden kann, dass man eine erste Spalte zweimal hintereinander löscht, aber ich denke, es wäre interessanter, ein wenig zu verallgemeinern.

Antwort1

Ich glaube, dies gilt speziell für Cut aus den GNU-Coreutils:

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

Normalerweise geben Sie die gewünschten Felder mit -f an, aber durch Hinzufügen von --complement kehren Sie die Bedeutung natürlich um. Aus 'man cut':

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

Eine Einschränkung: Wenn eine der Spalten ein Komma enthält, wird „cut“ ausgegeben, da „cut“ kein CSV-Parser im gleichen Sinne wie eine Tabellenkalkulation ist. Viele Parser haben unterschiedliche Vorstellungen davon, wie mit dem Escapen von Kommas in CSV umgegangen werden soll. Für den einfachen CSV-Fall ist „cut“ auf der Befehlszeile immer noch die beste Methode.

Antwort2

Wenn die Daten einfach aus durch Kommas getrennten Spalten bestehen:

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

Sie können auch awk verwenden, aber das ist etwas umständlich, denn während das Löschen eines Felds einfach ist, ist das Entfernen des Trennzeichens etwas Arbeit. Wenn Sie kein leeres Feld haben, ist es nicht so schlimm:

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

Wenn Sie eine echte CSV-Datei haben, in der Kommas innerhalb von Feldern erscheinen können, wenn sie richtig zitiert werden, benötigen Sie eineechte CSV-Bibliothek.

Antwort3

Verwenden eines CSV-fähigen Tools zum Entfernen der ersten beiden Spalten aus einer CSV-Eingabedatei ohne Kopfzeile:

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

Die -xOption zur cutOperation inMüller( mlr) bewirkt, dass die Operationausschließendie benannten Felder (in diesem Fall die Felder Nummer 1 und 2). Hätten die CSV-Daten Überschriften gehabt, hätten wir benannte Felder verwenden können -f(die -NOption müsste in diesem Szenario ebenfalls gelöscht werden).

Da Miller CSV-fähig ist, kommt es mit korrekt zitierten Feldern zurecht, die eingebettete Kommas, Anführungszeichen und Zeilenumbrüche enthalten.

Antwort4

Versuchen Sie den folgenden Befehl, um Spalten mithilfe des Index zu löschen.

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

Dies würde funktionieren, wenn die Spalten durch Kommas getrennt sind, wiesedInnerhalb der Funktion werden Befehle zum Entfernen von Zeichenfolgen verwendet.

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
}

verwandte Informationen