Wie kann ich Werte aus zwei Spalten kombinieren?


11

Ich habe eine Datei im folgenden Format:

$ cat /tmp/raw
2015-01   5000   1000
2015-02   6000   2000
2015-03   7000   3000

Ich möchte nun den kombinierten Wert aus den Spalten 2 und 3 in jeder Zeile abrufen, sodass die Ergebnisse wie folgt aussehen:

2015-01   6000
2015-02   8000
2015-03   9000

Ich habe es versucht, aber es zeigt nur den letzten Wert in der Datei wie den Wert 2015-03.

Antworten:


11

Sie können versuchen, Folgendes zu verwenden awk:

awk '{ print $1, $2 + $3; }' /tmp/raw

Ergebnis wird sein (ich nehme an, der Wert für 2015-03 sollte 10000 sein):

2015-01 6000
2015-02 8000
2015-03 10000

1
Ich kann nicht glauben, dass ich die Antwort so schnell bekommen habe: O, ich bekomme nie eine so schnelle Antwort in einem anderen Forum :) Danke, der Befehl hat perfekt funktioniert :)
Syed Jahanzaib

@SyedJahanzaib, Wenn diese Antwort Ihr Problem gelöst hat, nehmen Sie sich bitte einen Moment Zeit und akzeptieren Sie sie, indem Sie auf das Häkchen links klicken. Dadurch wird die Frage als beantwortet markiert und auf den Stack Exchange-Websites wird der Dank ausgesprochen.
Terdon

Entschuldigung, ich habe vergessen, die Antwort zu markieren. und danke auch allen anderen für die wertvolle Zeit und die Antworten, sie haben mir auch geholfen, das Erreichen von Zielen mit verschiedenen Methoden zu lernen :)
Syed Jahanzaib

@ SyedJahanzaib, obwohl ich mir für diese Antwort ein schönes Abzeichen verdient habe, denke ich, dass Terdons Antwort präziser und umfassender ist.
Taliezin

16

Hier sind einige Möglichkeiten:

  1. Ein weiterer awk Ansatz

    awk '{$2+=$3;}NF--' file
    
  2. Perl

    perl -lane 'print "$F[0] ",$F[1]+$F[2]' file
    

    oder

    perl -ape 's/$F[1].*/$F[1]+$F[2]/e' file
    
  3. Shell (viel langsamer / weniger effizient als oben)

    while read a b c; do echo "$a $((b + c))"; done < file
    

2
$2+=$3kann mehr awky sein.
123

@ User112638726 in der Tat ist es. Vielen Dank.
Terdon

3
Sie können auch verwenden, awk '{$2+=$3}NF--'damit noch kein leeres Feld 3 herumhängt. Obwohl das nur meine Präferenz ist und es zu ähnlich ist, um es als Antwort alleine zu posten :)
123

1
@ User112638726 jetzt, wo mir noch nicht einmal einer eingefallen war. Viel ordentlicher, danke!
Terdon

Ich habe das für dich geschrieben. Beachten Sie, dass es nicht nur sedirgendwie gelingt, Felder zu verstehen - selbst um Felder im laufenden Betrieb und Felder mit Feldern zu definieren -, sondern wie es anscheinend der Fall ist, das gesamte Konzept des Unix-Regexp-Abgleichs tatsächlich auf der Aufteilung einer Zeichenfolge in Felder basiert nach einem Muster ! Wer wusste?
Mikeserv

5
sed 's/[^ ]* */[&]P/;s//&+pc/3'|dc

... druckt ...

2015-01   6000
2015-02   8000
2015-03   10000

Daher deklariere ich oben einen regulären Ausdruck, der eine Feldausdehnung definiert , die aus einer einzelnen Folge von Zeichen *variabler Länge besteht, die ^nicht <Leerzeichen> sind, unmittelbar gefolgt von einer einzelnen Folge von Zeichen *variabler Länge, die <Leerzeichen> sind . Diese Deklaration wird auf sedden Musterbereich angewendet , bei dem es sich um eine Zeichenfolge handelt, die (standardmäßig) durch jedes \nbei der Eingabe vorkommende ewline-Zeichen begrenzt ist und die bei jedem Auftreten derselben rekursiv (standardmäßig) durch die nächste ersetzt wird.

Die Schnittstelle für diese Deklaration ist zweifach und wird auf jeder Ebene von mindestens einem internationalen IEEE-Standardkomitee vollständig reguliert und spezifiziert , um eine vorhersehbare Anwendung der sedBefehlssyntax sicherzustellen . sed‚s API - Syntax , ist beispielsweise in diesem Fall mit dem angelegten Adressenbefehl/ (die immer die erste Komponente jedes ist ubstitution - Befehls) , aber der Inhalt desselben wird durch einen basischen API als Teilmenge des für die angegebene interpretiert Funktion in der Standard-C-Bibliothek ./sed s///regcomp()

Ich kann diese Aussagen sicher machen, da sedes sich nicht nur um ein Programm handelt, sondern die kompilierte ausführbare Datei, die sedauf meinem Unix-ähnlichen Computer benannt ist, eine Implementierung der genau definierten, historisch etablierten und standardgesteuerten sed Anwendung der regulären Systemfunktionen meines Systems ist. Ausdrucks-Matching-Bibliotheken.


Aus der sedSpezifikation:

Das sedDienstprogramm muss die in XBD Basic Regular Expressions beschriebenen BREs unterstützen ...

... wo wir finden ...

Beide BREs und EREs werden durch die Regular Expression Matching - Schnittstelle im System Interfaces Volumen von POSIX.1-2008 unter unterstützten regcomp(), regexec()und die damit verbundenen Funktionen.

Eine Anwendung, die aufruft regcomp(), zeigt eine Musterzeichenfolge und ...

... [d] ie regcomp()Funktion wird mit dem regulären Ausdruck in der Zeichenfolge enthalten kompilieren vom deutete auf Muster Argumente und legen Sie die Ergebnisse in der Struktur preg ...

Um darauf zu reagieren, würde sich diese Anwendung dann auf die regcomp()Begleitfunktion beziehen ...

... [t] Die regexec()Funktion vergleicht die durch string angegebene nullterminierte Zeichenfolge mit dem kompilierten regulären Ausdruck preg, der durch einen vorherigen Aufruf von regcomp()... initialisiert wurde.

... regexec()soll die Elemente eines Arrays mit Offsets der Teilzeichenfolgen des Strings füllen, die den in \(Klammern gesetzten Unterausdrücken \)des Musters entsprechen ... Muster selbst zählt als Unterausdruck ...

... [t] Die regexec()Funktion muss alle nmatch- Elemente von pmatch ausfüllen , wobei nmatch und pmatch von der Anwendung bereitgestellt werden, auch wenn einige Elemente von pmatch nicht den Unterausdrücken im Muster entsprechen .


Und wenn ich das tue ...

/[^ ]* */

... kompiliertsed zuerst den regulären Ausdruck und speichert die Ergebnisse im Speicher, wendet dann den dort gespeicherten kompilierten Automaten so oft auf den Inhalt meines Musterraums an, wie zur Erfüllung meines Befehls erforderlich ist. Jedes Mal, wenn dies der Fall ist, ist das Ergebnis ein Array von einem oder mehreren nullbegrenzten Feldern , die bei den von zurückgegebenen Offsets begrenzt sind .regexec()

Und wenn ich ...

//

... um anzuzeigen, dass der zuletzt definierte reguläre Ausdruck verwendet werden soll, sedkönnen Sie regexec()den vorkompilierten regulären Ausdruck einfach erneut aufrufen, diesmal jedoch möglicherweise auf ein geändertes Zeichenfolgenargument anwenden oder neue nmatch- Parameter anwenden , wie ich es befehle.

Genauer gesagt noch ...

  • s/[^ ]* */[&]P/
    • Ersetzen Sie das erste Auftreten eines Musters im Musterraum durch eine [linke eckige Klammer, dann &selbst, dann durch eine ]rechte eckige Klammer, gefolgt von einem PZeichen.
  • s//&+pc/3
    • Wenden Sie den zuletzt verwendeten regulären Ausdruck erneut auf den aktuellen Musterraum an und ersetzen Sie das 3dritte Vorkommen eines Musters im Musterraum durch sich &selbst, gefolgt von der angehängten Zeichenfolge +pc.

Und so sedschreibt es für jede Zeile der Eingabe anhand Ihrer Beispieldaten in die Standardausgabe:

[2015-01   ]P5000   1000+pc
[2015-02   ]P6000   2000+pc
[2015-03   ]P7000   3000+pc

Dies mag seltsam aussehen, aber der dcTaschenrechner zitiert Zeichenfolgen in seiner Eingabe in eckigen Klammern, und der PBefehl druckt beide die Oberseite des Stapels, ohne eine \nneue Zeile anzuhängen, und entfernt diese anschließend vom Eingabestapel.

Wenn Sie also die erste Zeile als Beispiel verwenden, reicht dcdies aus:

  • [2015-01 ]P
    • Print und platzen Sie die Oberseite des Stapels
  • 5000
    • Schieben Sie die Zahl oben 5000auf den Stapel und drücken Sie alle Elemente auf dem Stapel (jetzt keine) um eins nach unten.
  • 1000
    • Das Gleiche gilt, aber diesmal wird die Zahl 5000 oben im Hauptstapel um eins nach unten gedrückt und wird zum zweiten Element auf dem Stapel.
  • +
    • Addieren Sie die beiden obersten Zahlen auf dem Stapel, nehmen Sie beide vom Stapel und schieben Sie die Summe auf die Oberseite des Stapels.
    • Dies führt zu einem Stapel, der nur aus der Zahl besteht 6000.
    • Dies ist ein Syntaxfehler, wenn eines der beiden obersten Elemente auf dem Stapel eine [Zeichenfolge ist ].
  • p
    • pDrucken Sie die Oberseite des Stapels, gefolgt von einer angehängten \nEwline, ohne sie vom Stapel zu entfernen.
  • c
    • cLerne den Stapel

Ich glaube, es funktioniert, aber ich kann es nicht analysieren. Insgesamt richten Sie einen Zusatz für DC ein. Das erste Muster macht Sinn. Ich denke, es stimmt mit dem Datum und den nachfolgenden Leerzeichen überein, aber ich verstehe nicht, was es bedeutet, wenn man das in die Klammern der Zeichenklasse ([&]) setzt. Es wäre großartig, wenn Sie dies buchstabieren würden.
Joe

1
@ Joe - besser?
Mikeserv

Beeindruckend! Das ist viel sinnvoller (und zeigt mir eine Reihe von Dingen, über die ich mehr lernen muss). Insbesondere hatte ich die Verwendung von // zur Wiederverwendung des aktuellen Musters nie bemerkt. So etwas lesen Sie durch und vergessen es, bis Sie auf ein aktuelles Beispiel stoßen. Danke vielmals. Es brachte mich zum Lachen, zu sehen, wie viel Kraft in einen winzigen Befehl gepackt werden konnte und wie viel es brauchte, um ihn zu erklären.
Joe

@ Joe - na ja ... vielleicht bin ich ein wenig über Bord
gegangen
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.