I am struggling with the following. I am using commands like this in my Mac terminal to test my regex:

echo 'inputstring' | sed (-E) '/s///g'

I am trying to create a regex that:

  • if and only if a word ends in the letter 'o', then:
  • deletes this word-final 'o'
  • replaces all occurrences of the letter 'i' to 'a' in this word

In this case, the inputstring is filo fililo felo fale and the expected output is fal falal fel fale

I can make a regex that does either the deletion or the replacement, but do not see how to combine them. If I put a semi column between them, I don't see how to put in the conditional part.

I am also having trouble defining 'the end of the word' position. I used \b but it doesn't seem to work (unlike $ for end of string).

  • post the actual, testable input string Commented Nov 19, 2017 at 20:28
  • Good point, I just added this to the description. As well as the expected outcome.
    – Triplesmeg
    Commented Nov 19, 2017 at 20:34
  • sed won't be good for such case. Use awk instead Commented Nov 19, 2017 at 20:49
  • sed idea; replace words that end in 'o' with '#word#' with stripped 'o', replace all 'i' between two '#' with 'a', remove all '#' that appear immediately before/after a word (replace my example '#' with any suitable character).
    – Hannu
    Commented Nov 19, 2017 at 21:22

3 Answers 3


I would not use sed for this, but if this is an exercise to learn sed, do a loop like this:

sed -E 's/$/ /
  s/ $//'
  • In the first line I add a whitespace at the end, so we can treat the line end like any word end. The last line removes that whitespace later.
  • The s command in line 3 searches for occurences of i in a word ending with o and replaces it with a. The t command loops back to mark :a to repeat this for all i in all o-ending words.
  • Now the fifth line removes the ending o and another loop. Note that from a word ending with oo, both of them will get removed; it's unclear whether this is desired.

For references only, I use an sed version supporting the o option to the s command meaning only to preserve the matched part and throw away the rest. Also it knows the \h in the replacement to replace by the contents of the hold space. This makes the task a one-liner:

sed -E ':a;h;s/([[:alnum:]]*)o($|[^[:alnum:]])/\1\2/o;T;y/i/a/;x;s//\h/;ba'

Awk would be more accurate and flexible for such case:

awk '{ for(i=1;i<=NF;i++) 
       if ($i~/o$/) { sub(/o$/,"",$i); gsub("i","a",$i) } }1' <<<"filo fililo felo fale"

The output:

fal falal fel fale

Alternative Python command line approach:

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

I'm not sure if this is possible to do with sed (I suspect that it probably isn't), but it's really easy to do with Python! Here's a script that does exactly what you want:

#!/usr/bin/env python2
# -*- coding: ascii -*-

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

You can run it like so:

echo 'filo fililo felo fale' | python modify_strings.py

And it produces the following output (as desired):

fal falal fel fale

If you really want sed to be involved, then you can probably get what you want by augmenting it with a little shell scripting. That might look something like the following 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$//';
        echo -n "${word} ";

You would call this script like so:

bash modify-strings.bash filo fililo felo fale
  • Everything is possible with sed, the question is whether it makes sense. In this case, I don't think so, see my answer for a solution.
    – Philippos
    Commented Nov 20, 2017 at 8:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .