Mein Verdacht ist, dass Sie es im Standard sed
nicht tun können , aber Sie könnten es mit Perl oder etwas anderem mit leistungsfähigerer Regex-Behandlung tun.
$ echo "She sells sea shells by the sea shore" |
> perl -pe 's/(sh[a-z]*)/"." x length($1)/gei'
... sells sea ...... by the sea .....
$
Die e
Modifikator bedeutet, dass das Ersetzungsmuster ein ausführbares Perl-Skript ist; in diesem Fall wiederholt es das Zeichen .
so oft, wie es Zeichen im übereinstimmenden Muster gibt. Die g
Modifikator wiederholt sich über die Zeile; die i
Modifikator ist für den Vergleich ohne Berücksichtigung der Groß-/Kleinschreibung. Die -p
Option zu Perl gibt jede Zeile nach der Verarbeitung in dem Skript aus, das durch den -e
angegeben ist Option — der Ersatzbefehl.
Erledigt dieser awk-oneliner die Arbeit für Sie?
awk '{for(i=1;i<=NF;i++)if($i~/^[Ss]h/)gsub(/./,".",$i)}1' file
Test mit Ihren Daten:
kent$ echo "She sells sea shells by the sea shore"|awk '{for(i=1;i<=NF;i++)if($i~/^[Ss]h/)gsub(/./,".",$i)}1'
... sells sea ...... by the sea .....
Eine alte Frage, aber ich habe eine nette und relativ kurze einzeilige Lösung gefunden:
sed ':a;s/\([Ss]h\.*\)[^\. ]/\1./;ta;s/[Ss]h/../g'
Funktioniert durch Ersetzen eines Zeichens nach dem anderen in einer Schleife.
:a;
eine Schleife starten
s/\([Ss]h\.*\)[^\. ]
Suche nach sh
gefolgt von einer beliebigen Zahl von .
s (unsere bisher abgeschlossene Arbeit) gefolgt von einem Nicht-Punkt- oder Leerzeichen (was wir ersetzen werden)
/\1./;
Ersetzen Sie es durch unsere bisher abgeschlossene Arbeit plus ein weiteres .
.
ta;
wenn wir eine Ersetzung vorgenommen haben, Schleife, sonst...
s/[Ss]h/../g
ersetzen Sie den sh
s mit zwei .
s und nennen Sie es einen Tag.