%20regul%C3%A4ren%20Ausdruck%2C%20der%20alle%20Vorkommen%20eines%20Zeichens%20ersetzt%20und%20das%20letzte%20l%C3%B6scht%3F.png)
Ich habe mit Folgendem zu kämpfen. Ich verwende Befehle wie diese in meinem Mac-Terminal, um meinen regulären Ausdruck zu testen:
echo 'inputstring' | sed (-E) '/s///g'
Ich versuche, einen regulären Ausdruck zu erstellen, der:
- genau dann, wenn ein Wort mit dem Buchstaben „o“ endet, dann:
- löscht dieses wortfinale 'o'
- ersetzt alle Vorkommen des Buchstabens 'i' durch 'a' in diesem Wort
In diesem Fall ist die Eingabezeichenfolge filo fililo felo fale
und die erwartete Ausgabe istfal falal fel fale
Ich kann einen regulären Ausdruck erstellen, der entweder die Löschung oder die Ersetzung vornimmt, weiß aber nicht, wie ich sie kombinieren kann. Wenn ich eine Halbspalte dazwischen setze, weiß ich nicht, wie ich den bedingten Teil einfügen kann.
Ich habe auch Probleme, die Position „Wortende“ zu definieren. Ich habe sie verwendet, \b
aber sie scheint nicht zu funktionieren (anders als $
beim Ende einer Zeichenfolge).
Antwort1
Ich würde es hierfür nicht verwenden sed
, aber wenn es eine Lernübung ist sed
, führen Sie eine Schleife wie diese aus:
sed -E 's/$/ /
:a
s/i([[:alnum:]]*o[^[:alnum:]])/a\1/
ta
s/([[:alnum:]]*)o([^[:alnum:]])/\1\2/
ta
s/ $//'
- In der ersten Zeile füge ich am Ende ein Leerzeichen hinzu, damit wir das Zeilenende wie jedes andere Wortende behandeln können. Die letzte Zeile entfernt dieses Leerzeichen später.
- Der
s
Befehl in Zeile 3 sucht nach Vorkommen voni
in einem Wort, das mit endet,o
und ersetzt es durcha
. Dert
Befehl springt zurück zur Markierung,:a
um dies für alle Wörter zu wiederholen, diei
mito
- enden. - Nun entfernt die fünfte Zeile die Endung
o
und eine weitere Schleife. Beachten Sie, dass aus einem Wort, das mit endetoo
, beide entfernt werden; es ist unklar, ob dies erwünscht ist.
Nur zu Referenzzwecken verwende ich eine sed
Version, die die o
Option für den s
Befehl unterstützt, die nur bedeutet, den übereinstimmenden Teil beizubehalten und den Rest wegzuwerfen. Außerdem kennt sie das \h
in der Ersetzung, das durch den Inhalt des Haltebereichs ersetzt werden soll. Dadurch wird die Aufgabe zu einem Einzeiler:
sed -E ':a;h;s/([[:alnum:]]*)o($|[^[:alnum:]])/\1\2/o;T;y/i/a/;x;s//\h/;ba'
Antwort2
Ohhhhwäre in einem solchen Fall genauer und flexibler:
awk '{ for(i=1;i<=NF;i++)
if ($i~/o$/) { sub(/o$/,"",$i); gsub("i","a",$i) } }1' <<<"filo fililo felo fale"
Die Ausgabe:
fal falal fel fale
AlternativePythonBefehlszeilenansatz:
python -c 'import sys,re; s = sys.stdin.read().strip();
print(re.sub(r"\b(\S+)o\b", lambda m: m.group(1).replace("i","a"), s))' <<<"filo fililo felo fale"
fal falal fel fale
Antwort3
Ich bin nicht sicher, ob das mit möglich ist sed
(ich vermute, dass es das wahrscheinlich nicht ist), aber mit Python ist es wirklich einfach! Hier ist ein Skript, das genau das macht, was Sie wollen:
#!/usr/bin/env python2
# -*- coding: ascii -*-
"""modify_strings.py"""
import sys
import re
import fileinput
# Iterate over lines of input
# (either read from files or from stdin)
for line in fileinput.input():
# Split each line into tokens and preserve whitespace
tokens = re.split(r'(\s+)', line)
# Iterate over tokens
for token in tokens:
# If a word ends in 'o' then
# perform the desired transformation
if token.endswith('o'):
token = token[:-1].replace('i', 'a')
# Print out each token
sys.stdout.write(token)
Sie können es wie folgt ausführen:
echo 'filo fililo felo fale' | python modify_strings.py
Und es erzeugt (wie gewünscht) die folgende Ausgabe:
fal falal fel fale
Wenn Sie wirklich sed
mitmachen möchten, können Sie Ihr Ziel wahrscheinlich erreichen, indem Sie es mit ein wenig Shell-Skripting erweitern. Das könnte etwa wie das folgende bash
Skript aussehen:
#!/usr/bin/env bash
# modify-strings.bash
for word in "$@"; do
if grep -q 'o$' <<<"${word}"; then
echo -n "${word} " | sed -e 's/i/a/g' -e 's/o$//';
else
echo -n "${word} ";
fi;
done
echo
Sie würden dieses Skript folgendermaßen aufrufen:
bash modify-strings.bash filo fililo felo fale