Wie erweitere ich diesen AWK-Spalte-2-Selektor mit dem Bash-Parameter $1?

Wie erweitere ich diesen AWK-Spalte-2-Selektor mit dem Bash-Parameter $1?

Ich versuche, aus meinem Bash-Skript eine Funktion mit Bash-Eingabeparameter zu machen, aber die AWK-Syntax verursacht ein Problem. Original-AWK-Code

http://stackoverflow.com/a/19602188/54964
awk -F "\"*,\"*" '{print $2}' textfile.csv

Pseudocode mit Bash-Parameter$1

file=$(awk -v colN="$1" -F "\"*,\"*" '{print $"${colN}"}' "${input}") 
# http://stackoverflow.com/a/19602188/54964 
# http://stackoverflow.com/a/19075707/54964

Das Problem ist das Teil print $"${colN}".

Die aktuelle Ausgabe erfasst die zweite Spalte nicht und nimmt die ganze Zeile usw. ein.

-0.21,-0.245
-0.205,-0.22

„Nur haben“ print $colNist nicht korrekt, da dann immer die erste Spalte unabhängig vom Wert in verwendet wird $1.

Beispiel für den Anwendungsfall, in dem ich es aufrufe bash code.bash 2; oder vollständiges SkriptHierDas funktioniert, wenn Sie nicht in allen zweispaltigen CSV-Dateien fest codieren, welche Spalte (1/2) für das verknüpfte Ergebnis der zweiten Spalten ausgewählt werden soll.

#!/bin/bash
ids=(101 118 201)
dir="/home/masi/Documents/CSV/"
index=0
for id in "${ids[@]}";
do
        input=$(echo "${dir}P${id}C1.csv")
        # take second column of the file here
        file=$(awk -v colN="$1" -F "\"*,\"*" '{print $colN}' "${input}") # http://stackoverflow.com/a/19602188/54964 # http://stackoverflow.com/a/19075707/54964

        Ecgs[${index}]="${file}"
        index=$index+1
done

Eingaben mehrspaltig 1.csv 2.csv 3.csv

-0.21,-0.245
-0.205,-0.22

Gewünschte Ausgabe

101,118,201
-0.245,-0.245,-0.245
-0.22,-0.22,-0.22

Betriebssystem: Debian 8.5
Bash 4.30

Antwort1

Ihre Beispieleingabe hat für alle Dateien die gleichen Werte im ersten und zweiten Feld (und für alle Dateien die gleichen Werte), was nicht wirklich hilft, den genauen Anwendungsfall zu verstehen. Wenn Sie tatsächlich dreimal den gleichen Wert haben möchten und ihn aus jedem Feld einer beliebigen Eingabedatei abrufen können, müssen Sie die anderen beiden Dateien nicht einmal überprüfen. Sie können einfach Folgendes verwenden:

cut -d, -f2 input.csv | paste -d, - - -

Natürlich funktioniert das nicht für echte Eingaben, sondern nur für Ihre Beispieleingaben. (Arbeiten Sie daran, Ihre Beispieleingaben/-ausgaben für diese Art von Fragen zu verbessern, es hilft einemviel.)


Wenn wir davon ausgehen, dass:

  • Sie haben immer genau drei Eingabedateien
  • Angerufen input1.csv, input2.csv,input3.csv
  • Mit jeweils genau zwei Spalten
  • Und Sie möchten die zweite Spalte aus jeder Datei

Am einfachsten gelingt dies mit einer Kombination aus Awk und paste(und Shell-Datei-Globbing):

paste -d, input[123].csv | awk -F, -v OFS=, '{print $2, $4, $6}'

Wenn diese Annahmen falsch sind, liegt die Schuld an schlechten Input-/Output-Beispielen. ;)

Antwort2

Um Ihre Frage wie angegeben zu beantworten,

$ cat file
a,b,c
d,e,f
g,h,i
j,k,l

und ein einfaches Testskript

$ cat col.bash
#!/bin/bash

awk -F, -vcol="$1" '{print $col}' file

Sie können überprüfen, ob $coltatsächlich auf die gewünschte Spalte verwiesen wird, d. h.

$ ./col.bash 2
b
e
h
k

Wenn das in Ihrem Fall nicht funktioniert, spielen andere Faktoren eine Rolle. Unabhängig davon gibt es weitaus einfachere Möglichkeiten, Spalten aus mehreren Dateien zu extrahieren.

Antwort3

Die Verwendung von Bash und AWK wird in diesem Fall sehr schwierig. Ich konnte das Problem mit den hier vorgeschlagenen Lösungen nicht lösen. Sie werden viele Probleme mit "/ '/... haben, daher ist hier ein einzelnes Tool erforderlich.

Verwenden Sie es gawkwie im Thread beschrieben.ECG Bash-Auswahltool.

# https://codereview.stackexchange.com/a/146370/122105
#!/usr/bin/gawk -f

# https://www.gnu.org/software/gawk/manual/html_node/Join-Function.html
@include "join.awk"

BEGIN {
    FS = "\"*,\"*";
    last_row = 0;
}

BEGINFILE {
    rows[0][ARGIND] = gensub(".*P([0-9]*)C.*", "\\1", "g", FILENAME);
}

{
    rows[FNR][ARGIND] = $col;
    if (FNR > last_row) { last_row = FNR; }
}

END {
    for (r = 0; r <= last_row; r++) {
        print join(rows[r], 1, ARGC - 1, ",");
    }
}

Bitte lesen Sie die vollständige Antwort von200_success Hiermit hervorragenden Erklärungen.

verwandte Informationen