Antworten:
Verwenden von sed
:
sed -E 's/((^| )2:)[^ ]*/\10/g' in > out
Auch, wie inspiriert souravc Antwort , wenn es nicht eine Chance auf einen 2:
Teilstring nach dem Beginn eines Strings nicht ein führendes enthält 2:
String (zB gibt es nicht eine Chance auf eine 1:202:25
Zeichenfolge, die der folgende Kurzbefehl ersetzen würde 1:202:0
), das Befehl kann auf diesen verkürzt werden:
sed -E 's/2:[^ ]*/2:0/g' in > out
Befehl # 1 / # 2 Aufschlüsselung :
-E
: lässt sed
das Muster als ERE-Muster (Extended Regular Expression) interpretieren;> out
: leitet weiter stdout
zu out
;sed
Befehl # 1 Aufschlüsselung :
s
: behauptet, eine Substitution durchzuführen/
: Startet das Muster(
: Startet die Erfassungsgruppe(
: Startet die Gruppierung der zulässigen Zeichenfolgen^
: Entspricht dem Zeilenanfang|
: trennt die zweite zulässige Zeichenfolge
: Entspricht einem
Zeichen)
: Beendet die Gruppierung der zulässigen Zeichenfolgen2
: Entspricht einem 2
Zeichen:
: Entspricht einem :
Zeichen)
: Stoppt die Erfassungsgruppe[^ ]*
: Entspricht einer beliebigen Anzahl von Zeichen nicht
/
: stoppt das Muster / startet die Ersatzzeichenfolge\1
: Rückreferenz durch die erste Erfassungsgruppe ersetzt0
: fügt ein 0
Zeichen hinzu/
: stoppt die Ersatzzeichenfolge / startet die Musterflagsg
: behauptet, die Ersetzung global durchzuführen, dh jedes Vorkommen des Musters in der Zeile zu ersetzensed
Befehl # 2 Aufschlüsselung :
s
: behauptet, eine Substitution durchzuführen/
: Startet das Muster2
: Entspricht einem 2
Zeichen:
: Entspricht einem :
Zeichen[^ ]*
: Entspricht einer beliebigen Anzahl von Zeichen nicht
/
: stoppt das Muster / startet die Ersatzzeichenfolge2:0
: fügt eine 2:0
Zeichenfolge hinzu/
: stoppt die Ersatzzeichenfolge / startet die Musterflagsg
: behauptet, die Ersetzung global durchzuführen, dh jedes Vorkommen des Musters in der Zeile zu ersetzenDieser eine Liner mit sed
sed -i.bkp 's/2:\([0-9]*\)\|2:\(-\)\([0-9]*\)/2:0/g' input_file
wird ersetzen global in Zeile in input_file
eine Backup - Datei mit dem Namen hält input_file.bkp
im gleichen Verzeichnis.
Dies kann weiter verkürzen erweiterte reguläre Ausdrücke verwenden , wie vorgeschlagen von kos, wie
sed -ri.bkp 's/2:\-?[0-9]*/2:0/g' input_file
2:
und 2:-
nur die -
optionale Übereinstimmung mit erweiterten regulären Ausdrücken vornehmen möchten ( -r
Option); Außerdem müssen Sie nichts erfassen, da Sie nichts ersetzen:sed -ri.bkp 's/2:\-?[0-9]*/2:0/g' input_file
Ich würde eine Basisschleife verwenden awk
:
$ awk '{for (i=1; i<=NF; i++) $i~/^2:/ && $i="2:0"}1' file
1:20 2:0 3:0.432 2:0 10:12
Dies durchläuft alle Felder. Immer wenn einer von ihnen mit beginnt 2:
, ersetzt er alles durch 2:0
. Schließlich 1
steht das für True, so dass die gesamte Zeile gedruckt wird.
Verwenden von python
:
#!/usr/bin/env python2
import re
with open('test_dir/unix_se.txt') as f:
for line in f:
print re.sub(r'(?:(?<=(?: 2:))|(?<=(?:^2:)))[^ ]*', '0', line).rstrip()
Hier haben wir die re.sub
Funktion des re
Moduls verwendet.
re.sub()
hat das Muster sub(pattern, repl, string, count=0, flags=0)
Da wir die Werte innerhalb der Gruppe nicht weiter verwenden werden, haben wir die nicht erfassende Gruppennotation verwendet (?:)
(?:(?<=(?: 2:))|(?<=(?:^2:)))
Verwendet den positiven Blick nach hinten mit der Breite Null, um 2:
zu Beginn oder gefolgt von einem Leerzeichen übereinzustimmen.
[^ ]*
Entspricht null oder mehr Zeichen vor dem Leerzeichen, danach 2:
und ersetzt sie durch 0
.
Hier ist ein Beispiel:
Eingang:
2:456 1:20 2:25 3:0.432 2:-17 10:12
1:20 2:25 3:0.432 2:-17 10:12 2:543 2:-78
Ausgabe:
2:0 1:20 2:0 3:0.432 2:0 10:12
1:20 2:0 3:0.432 2:0 10:12 2:0 2:0
Danke @kos für die sed
Version:
Einige kleine Modifikationen für den perl
Weg:
perl -pe 's/((^|\s)2:)[^\s]*/${1}0/g' testdata
Schreiben Sie zurück mit:
perl -i -pe 's/((^|\s)2:)[^\s]*/${1}0/g' testdata
Erläuterung:
((^|\s)2:)[^\s]*
1. Erfassungsgruppe ((^|\s)2:)
(^|\s)
1. Alternative: ^
^
Position am Anfang der Zeichenfolge bestätigen
2. Alternative: \s
\s
Entspricht einem beliebigen Leerzeichen [\r\n\t\f ]
2:
stimmt 2:
buchstäblich mit den Zeichen überein
[^\s]*
stimmen mit einem einzelnen Zeichen überein, das in der folgenden Liste nicht vorhanden ist
Quantifizierer: *
Zwischen null und unbegrenzt, so oft wie möglich, nach Bedarf zurückgeben [gierig]
\s
Entspricht einem beliebigen Leerzeichen [\r\n\t\f ]
Oder mit einem positiven Lookbehind , thx @steeldriver
perl -pe 's/(?<=2:)\S*/0/g' testdata
Erläuterung
(?<=2:)\S*
(?<=2:)
Positives Aussehen - Stellen Sie sicher, dass der unten stehende reguläre Ausdruck übereinstimmen kann
2:
passt zu den Zeichen 2
: buchstäblich
\S*
Entspricht einem beliebigen Leerzeichen [^\r\n\t\f ]
Quantifizierer: *
Zwischen null und unbegrenzt, so oft wie möglich, nach Bedarf zurückgeben [gierig]
s/(?<=2:)\S*/0/g
(alle folgenden Folgen von Nicht-Leerzeichen ersetzen 2:
durch 0
)?
S+
als S*
eine leere Zeichenfolge zu ersetzen, 2:
dh 2:
wird 2:0
, was möglicherweise nicht das beabsichtigte Verhalten ist
2:
genau passenden Strings ? Sollten diese ersetzt werden?