2017-01-28 9 views
0

Ich möchte jede Instanz von word ersetzen, die nicht das Präfix pre hat, mit preword unter Verwendung von sed. So ist die word in preword sollte nicht ersetzt werden, sondern eine einsames word sollte mit preword ersetzt werden.Ersetzen Sie Wörter, die nicht mit einem bestimmten Präfix beginnen, mithilfe von sed

habe ich versucht, die üblichen negativen Blick hinter regex wie so

sed -E -i 's/(?<!pre)word/preword/g'

aber es gibt mir den Fehler

sed: -e expression #1, char 22: Invalid preceding regular expression

ich gelesen habe, dass GNU sed einige verschiedene Möglichkeiten hat von Regex zu behandeln. Was kann ich tun, um dies zu erreichen?

+0

Sollte 'foreword' werden' forepreword'? Klären Sie Ihre Anforderungen und zeigen Sie eine übersichtliche, testbare Eingabe und erwartete Ausgabe, die alle Ihre Anwendungsfälle abdeckt. –

Antwort

2

Mit GNU sed:

sed 's/\bword\b/preword/g' file 

\b ist eine Null-Breite Wortgrenze

+0

Okay, das hat den Trick gemacht! Danke @Cyrus! :) – samurdhilbk

+2

Nachteil: Es ersetzt nicht "microsoftword". – Cyrus

+0

Ich sehe. Aber meine Anwendung möchte eigentlich nur Wörter ersetzen, die am Anfang eine Grenze haben. – samurdhilbk

3

Sie müssen das nicht vermeiden "Wort" mit "pre" vor, passen " pre“ersetzen und es systematisch:

sed -E 's/(pre)?word/preword/g' 

Andere Art und Weise (allgemeine), setzen Sie in eine Capture-Gruppe, dass alle nicht „pre“:

sed -E 's/(^|[^e]|^e|[^r]e|^re|[^p]re)word/\1preword/g' 
0

Wenn Sie eine komplexe reguläre Ausdrücke müssen auch Schreiben eines kleinen Parser betrachten können.

$ cat r.awk 
BEGIN { 
    re_wrd = "^[A-Za-z]+" # what we consider a word 
    re_sep = "^."  # the rest is a separator 
} 

function advance() { # sets `tag' and `tok'; eats a part of `line' 
    if  (match(line, re_wrd)) tag = "wrd" 
    else if (match(line, re_sep)) tag = "sep" 
    tok = substr(line, 1,   RLENGTH) 
    line = substr(line, RLENGTH + 1  ) 
} 

function process_sep() { # copy to output 
    ans = ans tok 
} 

function process_wrd() { 
    sub(/^word/, "preword", tok) # replace only at the beginning 
    ans = ans tok 
} 

{ 
    line = $0; ans = tag = tok = "" 
    while (length(line) > 0) { 
     advance() 
     # uncomment for tracing 
     # print tag, "<" tok ">" | "cat 1>&2" 
     if  (tag == "sep") process_sep() 
     else if (tag == "wrd") process_wrd() 
    } 
    print ans 
} 

Verbrauch:

$ echo 'preword...microsoftword word wordword,word.word-preword' | awk -f r.awk 
preword...microsoftword preword prewordword,preword.preword-preword 

Trace:

wrd <preword> 
sep <.> 
sep <.> 
sep <.> 
wrd <microsoftword> 
sep < > 
wrd <word> 
sep < > 
wrd <wordword> 
sep <,> 
wrd <word> 
sep <.> 
wrd <word> 
sep <-> 
wrd <preword> 
+1

Das Anwendungsbeispiel mit' echo' und Backticks würden einen Fehler verursachen, nicht wahr? –

+0

@BenjaminW. Fest. Vielen Dank. – slitvinov

Verwandte Themen