awk sed if Aussage

9

Ich versuche, 0 am Anfang hinzuzufügen, WENN es ein "" gibt. am 2. Zeichen dieser Zeile. Ich konnte diese beiden nicht kombinieren;

awk '{ print substr( $0, 2, 1 ) }' file.txt 

zeigt das zweite Zeichen

sed -ie "s/.\{0\}/0/" file.txt

am Anfang eine Null hinzufügen.

Es sollte ein "wenn das zweite Zeichen ein Punkt ist" stehen.

Beispieldatei:

1.02.2017 23:40:00
10.02.2017 23:40:00

Finale:

01.02.2017 23:40:00
10.02.2017 23:40:00
G.Ahmet
quelle

Antworten:

12

Wir können entweder das Problem verwenden sedoder awkes vollständig lösen.


Mit sed:

$ sed 's/^.\./0&/' file.txt

Wenn dies &im Ersatzteil des Ersetzungsbefehls ( s) auftritt , wird es auf den Teil der Eingabezeile erweitert, der dem Musterteil des Befehls entspricht.

Der reguläre Ausdruck ^.\.bedeutet " Alle Zeilen, die mit ( ^) beginnen, mit einem beliebigen Zeichen ( .) gefolgt von einem Literalpunkt ( \.) abgleichen ".

Wenn die Linie ist 1.02.2017 23:40:00, stimmt das Muster überein und 1.wird 01.am Anfang der Linie durch ersetzt.


Mit awk:

Aufbauend auf dem awkTeilcode in der Frage ...

Dadurch wird, wie angegeben, das zweite Zeichen jeder Eingabezeile gedruckt:

$ awk '{ print substr($0, 2, 1) }' file.txt

Wir können die Tatsache verwenden, dass substr($0, 2, 1)das zweite Zeichen zurückgegeben wird, und dies als Bedingung verwenden:

$ awk 'substr($0, 2, 1) == "." { ... }' file.txt

Was geht, { ... }ist Code, der vorangestellt ist $0, was der Inhalt der aktuellen Zeile ist, mit einer Null, wenn die vorhergehende Bedingung wahr ist:

$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 }' file.txt

Dann müssen wir nur noch sicherstellen, dass alle Zeilen gedruckt werden:

$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 } { print }' file.txt

Die Bedingung substr($0, 2, 1) == "."kann natürlich auch in einen regulären Ausdruck geändert werden (wir verwenden genau den gleichen Ausdruck wie in der sedLösung):

$ awk '/^.\./ { $0 = "0" $0 } { print }' file.txt

Einige Leute, die denken, "kürzer ist immer besser", würden das als schreiben

$ awk '/^.\./ { $0 = "0" $0 } 1' file.txt

(und wahrscheinlich auch entfernen , die meisten Räume: awk '/^.\./{$0="0"$0}1' file.txt)

Kusalananda
quelle
1
+1 Ihr letztes AWK-Beispiel oder Ihr sed-Beispiel sind die richtigen Möglichkeiten, dies zu tun. Beachten Sie der Klarheit halber, dass es nur das eine oder andere sein würde.
Bis auf weiteres angehalten.
Meiner Meinung nach ist der "richtige" Ansatz (der nicht mit Leerzeichen spielt und der sowieso leichter ist) Ihre endgültige Version sed 's/^.\./0&/' file.txt. Ich denke, Sie sollten das am Anfang dieser Antwort setzen. Trotzdem +1.
Wildcard
1
@ Wildcard Wir möchten bitte.
Kusalananda
5

Mit sed:

sed -e "/^.\./s/^/0/" file.txt 

Das Muster /^.\./sucht nach einem beliebigen Zeichen und einem Literalpunkt am Zeilenanfang ^. Wenn dies übereinstimmt, sersetzen Sie diesen Zeilenanfang durch eine Null und fügen Sie die Null effektiv zum Anfang hinzu.

Das sed expressoin s/.\{0\}/0/ist etwas seltsam, es entspricht null oder mehr Kopien von irgendetwas und wird durch eine Null ersetzt. Das Muster stimmt natürlich an jeder Position der Zeichenfolge überein, aber da es s///nur die erste Übereinstimmung ersetzt, funktioniert es wie beabsichtigt. Ein kurioser Weg, dies zu tun.


Oder mit awk würde ein ähnlicher Regex funktionieren, um der Linie zu entsprechen, aber wir können verwenden substr:

awk 'substr($0, 2, 1) == "." {$0 = "0" $0} 1' file.txt 

Wir testen zuerst, ob das zweite Zeichen ein Punkt ist, und fügen dann eine Null an der Vorderseite der Zeile hinzu, wenn dies der Fall ist. Der letzte Aufruf ruft die Standardaktion zum Drucken der Zeile nach Änderungen auf.

ilkkachu
quelle
4

Sie sagten awk und sed, aber es scheint, als würden Sie versuchen, ein Datum zu formatieren, und dafür würde ich den dateBefehl verwenden. Zum Beispiel:

echo '1.2.2017 23:40:00' | sed 's/\./\//g' | xargs -0 date '+%m.%d.%Y %T' -d

wird ausgegeben

01.02.2017 23:40:00

Der sedBefehl in der Mitte ändert die Punkte in Schrägstriche für die Eingabe in date -d. Die Formatoptionen ermöglichen die Ausgabe in nahezu jedem gewünschten Format. Der %minsbesondere Null-pad des Monat, das ist , was es scheint , wie Sie zu tun versuchen.

Wie Kusalananda betont:

Noch kompakter (GNU-Datum und Bash): date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'

bmb
quelle
2
Schöner Fang! Noch kompakter (GNU-Datum und Bash):date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'
Kusalananda
Immer wenn ich Schrägstriche in meinen Mustern habe, aber keine Pfeifen : s|\.|/|g. Ansonsten, wie oben erwähnt: Netter Fang, +1
Alex Stragies
2

Eine andere Strategie als in den anderen Antworten dargestellt: Sie könnten "." als Feldtrennzeichen.

awk -F. '$1 < 10 {printf "0"} {print}' /tmp/in.txt

Sie könnten dies Golf spielen, um:

awk -F. '$1<10{printf "0"}1' /tmp/in.txt

Für sed gibt es einen kürzeren Befehl, der in einer anderen (großartigen) Antwort dargestellt wird.

Alex Stragies
quelle
1
Alternative: awk -F. '{print ($1<10?0$0:$0)}' file
George Vasiliou
1

Mit sed könnte es sein

sed 's/^\(.\)\.\(.*\)/0\1.\2/'

Dies wird verwendet ^, um am Anfang der Zeile zu verankern und dann ein einzelnes Zeichen in einer Gruppe zu erfassen, gefolgt von einem Literal .und allem anderen. Wenn wir übereinstimmen, drucken wir a 0, dann unsere erste Erfassungsgruppe (das Zeichen am Anfang der Zeile), dann a und .dann unsere zweite Erfassungsgruppe (den Rest der Zeile)

Eric Renouf
quelle
Es ist überhaupt nicht notwendig, irgendetwas davon zu erfassen. &ist dein Freund. Siehe Kusalanandas Beispiel.
Bis auf weiteres angehalten.
@ TennisWilliamson nicht notwendig, aber da es bereits andere Beispiele gibt, zeigt dies, dass ein anderes Merkmal seddavon in anderen Situationen nützlich sein könnte, nicht nur dieses spezifische Problem
Eric Renouf