2016-09-25 6 views
1

Ich bin eine CSV-Datei durchlaufen. Jede Zeile der Datei ist so etwas wie dieses formatiert (es ist Open Street Maps-Daten):Drucken, ändern, erneut drucken Bash Variable

planet_85.287_27.665_51a5fb91, AcDbEntity: AcDbPolyline, {[name] Purano Bus Park-Thimi [Art] route [Route ] microbus [ref] 10} {[Id] 13,0 [Srid] 3857 [FieldsTableId]

Dies folgt dem Format:

Schicht, Subklassen, ExtendedEntity, Linientyp, EntityHandle, Text

Ich möchte eine neue Spalte für Name hinzuzufügen. Ich finde den Namen in einer Zeile, indem ich alles vor [Name] und nach [. Dieser Code erstellt erfolgreich eine neue Zeile mit allen Namen (die ich als CSV öffne und dann als neue Spalte in die Originaldatei kopiere).

cat /path/to/myfile.csv | while read line 
    do 
    if [[ ${line} == *"name"* ]] 
     then 
      printf "$(echo $line | LC_ALL=C sed 's/^.*name\]//g'| LC_ALL=C cut -f1 -d'[') \n" 
     else 
      printf "\n" 
    fi 
done >/path/to/newrow.csv 

Dieses System ist eindeutig suboptimal - ich würde viel lieber die gesamte letzte Zeile drucken. Aber wenn ich diese Printf-Zeile mit diesem ersetzen:

Es druckt die Zeile, aber nicht den Namen. Ich habe versucht, sie in separaten Druckanweisungen zu drucken, die Zeile auszudrucken und dann den Namen zu wiederholen, den Namen in einer Variablen zu speichern und dann zu drucken, und eine Reihe anderer Techniken, und jedes Mal a) nur die Zeile auszudrucken, oder b) Drucken Sie den Namen auf eine neue Zeile, die das CSV-Format bricht.

Was mache ich falsch? Wie kann ich die vollständige Originalzeile mit dem angehängten Namen am Ende als neue Spalte drucken?

HINWEIS: Ich verwende diese im Terminal auf macOS Sierra auf einem MacBook Pro 15" Retina

+1

FYI - mit 'printf', Substitutionen sollte nur in nachfolgenden Argumenten sein, nicht die Formatzeichenfolge selbst. –

+1

... und das Ausführen von 'sed' und' cut' einmal pro Zeile ist sehr, * sehr * ineffizient - wenn Sie Ihre Verarbeitung zeilenweise durchführen möchten, versuchen Sie [bash-native String-Manipulation] (http://mywiki.wooledge.org/BashFAQ/100) statt. –

+0

@CharlesDuffy danke für die Eingabe. Ich werde morgen noch mehr Manpages lesen. Ich habe einen sehr strengen Kurs auf Bash und C absolviert, aber es war vielleicht vor 5 Monaten und ich habe seitdem keine mehr gemacht, daher bin ich im Moment völlig außer Übung! –

Antwort

1

Wenn ich das richtig verstanden, Sie den Namen zwischen [name] und [type], und fügen Sie als neuen letzten CSV extrahieren möchten. . Spalte können Sie tun das, indem Einfanggruppen.

sed -e 's/.*\[name\] \(.*\) \[type\].*/&,\1/' < input 

Beachten Sie die \(.*\) in der Mitte, erfasst den Text zwischen [name] und [type]

.

In der Ersatzzeichenfolge, & steht für die einstimmenden Zeichenkette, die die gesamte Zeile ist, wie das Muster beginnt und endet mit .*. Als nächstes werden die , ist eine wörtliche Komma und \1 steht für den Inhalt der ersten Einfang-Gruppe, die innerhalb von \(...\) angepaßten Teil.

+0

Das hat funktioniert, danke. Das heißt, macOS-Benutzer müssen LC_ALL = C hinzufügen, wenn sie sed und andere Tools verwenden, um Warnungen zu vermeiden. –

+1

Nicht notwendig. Das hängt von Ihrer Umgebung ab. Ich bin auch auf OSX, und ich musste es nicht hinzufügen, und ich habe 'LC_ALL = en_US.UTF-8' – janos

+0

interessant - haben Sie etwas Besonderes getan, um Ihre Maschine einzurichten, um eine Standard-SED zu verwenden? Oder bin ich auf Sierra, die eine BSD-Version verwendet? –