Ich habe den folgenden Datenrahmen, der horizontal und vertikal unbegrenzt mit negativen Zahlen nur in den ungeraden Spalten fortgesetzt wird:
-1 2 3 4 -5 9
2 3 -4 5 -6 11
Und ich möchte die 2., 4. und 6. vollständige Spalte (oder jede gerade Spalte) und die Minuszeichen nur von der 1., 3. und 5. (oder jeder ungeraden Spalte), also bekomme ich Folgendes:
- 2 4 - 9
3 - 5 - 11
Und am Ende damit:
-2 4 -9
3 -5 -11
Ich brauche also die Werte aus den geraden Spalten unverändert und aus den ungeraden Spalten. Wenn es einen negativen Wert gibt, behalte den - only und wenn es einen positiven Wert gibt, verwerfe ihn.
Gibt es eine Möglichkeit, dies mit awk / sed zu tun?
Dies ist ungefähr so weit wie ich komme:
awk '{ for (i=2;i<=NF;i+=2) $i="" }1' FILE.txt | sed 's/[0-9,.]*//g'
text-processing
sed
awk
Wie gefunden
quelle
quelle
Antworten:
Hier ist eine Möglichkeit:
Das
awk
Skript geht alle ungeraden Spalten durch und setzt ihren Wert auf,-
wenn sie negativ und leer sind, wenn nicht. Anschließend werdensed
alle Leerzeichen nach a entfernt-
und mehrere aufeinanderfolgende Leerzeichen durch ein einzelnes ersetzt. Beachten Sie, dass dies bedeutet, dass die Ausrichtung unterbrochen wird, da einige Felder zwei oder mehr Zeichen und andere eines haben. Das ist kein Problem, wenn Sie mit Feldern arbeiten, sie sehen einfach nicht hübsch aus.quelle
Der
sed
Weg:Ausgabe:
Der erste Ausdruck beendet die nachfolgende Spalte, wenn eine ungerade Anzahl von Spalten vorhanden ist. Dazu werden 0 oder mehr Paare gesucht
<number> <number>
, wobei die erste Zahl negativ sein kann.Bearbeiten: Eine kürzere
sed
Lösung, inspiriert von @mikeserv:Das gleiche mit
perl
:Ein anderer Weg mit
perl
(wahrscheinlich dem saubersten):quelle
Eine
perl
Eins:-an
Eingabe in@F
Array aufteilenBEGIN{$,=" "}
Setzen Sie das Ausgabefeldtrennzeichen auf ein Leerzeichengrep{!($_%2)}0..$#F
Holen Sie sich alle geraden Indizes im@F
Array, die Indizes von ungeraden Elementen sindmap{$_=$F[$_]=~/^-/?"-$F[$_+1]":" $F[$_+1]"}
Überprüfen Sie, ob ein ungerades Element mit beginnt-
, und hängen Sie es-
an das nächste gerade Element an. Andernfalls fügen Sie ein Leerzeichen hinzuquelle
Als Antwort von @ terdon, aber ohne sed:
quelle
Eine
python
Lösungquelle
Eine einfache mathematikbasierte
awk
Lösung:i=2
) zum letzten Feld (i<=NF
).$(i-1)
) mit -1 oder 1.printf "%4s"
) und drucken Sie eine nachfolgende Newline (print ""
).Die einzige Einschränkung besteht darin, dass im letzten Feld bei einer ungeraden Anzahl von Spalten überhaupt nichts angezeigt wird. Ich hoffe das ist was du erwartest.Anscheinend ist es das, was Sie erwarten. :) :)(bearbeitet, um mit Dezimalwerten zu arbeiten und die Schleifenbedingungen besser an die Frage anzupassen, während 2 Zeichen gespeichert werden.)
quelle
Sie müssen das Negative ganz vergessen - lassen Sie es weg. Sie möchten zwei Felder konsolidieren - von links nach rechts. Das ist sehr einfach.
Beachten Sie, wie ich jegliche Bezugnahme auf das Zeichen überhaupt vermeide - wenn die Eingabe verarbeitet wird, akzeptiert der Automat nur Leerzeichen oder Zahlen, weil er nichts anderes versteht - alles andere wird vollständig ignoriert und bleibt an Ort und Stelle.
Wenn Sie ein
\{
numerisches Wiederholungsintervall\}
für einen\(
Unterausdruck angeben\)
, wird nur auf das letzte Vorkommen dieses Ausdrucks\1
verwiesen. So können Sie ein Wiederholungsintervall so einfach drücken oder abschneiden. Und weil wir die Wiederholung hinter dem Zeichen drücken - falls es eines gibt - folgt das zweite Auftreten dieses Musters jedem Zeichen, das vor dem ersten vorangestellt war.Das oben beschriebene Verhalten wird von POSIX für alle BRE-kompatiblen Anwendungen angegeben, aber nur sehr wenige
sed
machen es richtig. GNUsed
tut es.Zuletzt dienen die Leerzeichen nur dazu, das Auftreten des Musters regelmäßig zu machen .
Natürlich wird dies bei Ihnen niemals funktionieren. Oder, wahrscheinlich richtiger, es wird immer für Sie funktionieren, aber niemals Ergebnisse zurückgeben. Wie könnte es sein, wenn das Muster unbestimmt ist ?
quelle