
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 $colN
ist 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 $col
tatsä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 gawk
wie 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.