%20que%20reemplace%20todas%20las%20apariciones%20de%20un%20car%C3%A1cter%20mientras%20se%20elimina%20el%20%C3%BAltimo%3F.png)
Estoy luchando con lo siguiente. Estoy usando comandos como este en mi terminal Mac para probar mi expresión regular:
echo 'inputstring' | sed (-E) '/s///g'
Estoy intentando crear una expresión regular que:
- si y sólo si una palabra termina en la letra 'o', entonces:
- elimina esta 'o' final de palabra
- reemplaza todas las apariciones de la letra 'i' por 'a' en esta palabra
En este caso, la cadena de entrada es filo fililo felo fale
y la salida esperada esfal falal fel fale
Puedo crear una expresión regular que elimine o reemplace, pero no veo cómo combinarlas. Si pongo una semicolumna entre ellas, no veo cómo poner la parte condicional.
También tengo problemas para definir la posición "el final de la palabra". Lo usé \b
pero no parece funcionar (a diferencia $
del final de la cadena).
Respuesta1
Yo no lo usaría sed
para esto, pero si es un ejercicio para aprender sed
, haz un bucle como este:
sed -E 's/$/ /
:a
s/i([[:alnum:]]*o[^[:alnum:]])/a\1/
ta
s/([[:alnum:]]*)o([^[:alnum:]])/\1\2/
ta
s/ $//'
- En la primera línea agrego un espacio en blanco al final, para que podamos tratar el final de la línea como cualquier final de palabra. La última línea elimina ese espacio en blanco más adelante.
- El
s
comando en la línea 3 busca apariciones dei
en una palabra que termina eno
y la reemplaza cona
. Elt
comando vuelve a marcar:a
para repetir esto para todas las palabras que terminani
en todaso
. - Ahora la quinta línea elimina el final
o
y otro bucle. Tenga en cuenta que a partir de una palabra que termina enoo
, se eliminarán ambas; No está claro si esto es lo que se desea.
Solo como referencia, utilizo una sed
versión que admite la o
opción del s
comando, lo que significa solo preservar la parte coincidente y desechar el resto. También conoce el \h
reemplazo para reemplazar por el contenido del espacio de retención. Esto hace que la tarea sea de una sola línea:
sed -E ':a;h;s/([[:alnum:]]*)o($|[^[:alnum:]])/\1\2/o;T;y/i/a/;x;s//\h/;ba'
Respuesta2
awkSería más preciso y flexible para tal caso:
awk '{ for(i=1;i<=NF;i++)
if ($i~/o$/) { sub(/o$/,"",$i); gsub("i","a",$i) } }1' <<<"filo fililo felo fale"
La salida:
fal falal fel fale
AlternativaPitónenfoque de línea de comando:
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
Respuesta3
No estoy seguro de si es posible hacer esto sed
(sospecho que probablemente no lo sea), ¡pero es realmente fácil de hacer con Python! Aquí hay un script que hace exactamente lo que desea:
#!/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)
Puedes ejecutarlo así:
echo 'filo fililo felo fale' | python modify_strings.py
Y produce el siguiente resultado (según se desee):
fal falal
Si realmente desea sed
participar, probablemente pueda obtener lo que desea aumentándolo con un poco de script de shell. Podría parecerse al siguiente bash
script:
#!/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
Llamarías a este script así:
bash modify-strings.bash filo fililo felo fale