%2C%20%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD%D1%8F%D1%8E%D1%89%D0%B5%D0%B5%20%D0%B2%D1%81%D0%B5%20%D0%B2%D1%85%D0%BE%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BE%D0%B4%D0%BD%D0%BE%D0%B3%D0%BE%20%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%D0%B0%20%D0%B8%20%D1%83%D0%B4%D0%B0%D0%BB%D1%8F%D1%8E%D1%89%D0%B5%D0%B5%20%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B8%D0%B9%3F.png)
Я борюсь со следующим. Я использую такие команды в терминале Mac, чтобы проверить свое регулярное выражение:
echo 'inputstring' | sed (-E) '/s///g'
Я пытаюсь создать регулярное выражение, которое:
- тогда и только тогда, когда слово заканчивается на букву «о», то:
- удаляет это слово с конечной буквой «о»
- заменяет все вхождения буквы «i» на «a» в этом слове
В этом случае входная строка filo fililo felo fale
и ожидаемый выводfal falal fel fale
Я могу сделать регулярное выражение, которое делает либо удаление, либо замену, но не вижу, как их объединить. Если я поставлю между ними полустолбец, я не вижу, как вставить условную часть.
У меня также возникли проблемы с определением позиции 'конец слова'. Я использовал, \b
но это, похоже, не работает (в отличие $
от конца строки).
решение1
Я бы не стал использовать sed
это, но если это упражнение для обучения sed
, сделайте такой цикл:
sed -E 's/$/ /
:a
s/i([[:alnum:]]*o[^[:alnum:]])/a\1/
ta
s/([[:alnum:]]*)o([^[:alnum:]])/\1\2/
ta
s/ $//'
- В первой строке я добавляю пробел в конце, так что мы можем рассматривать конец строки как конец любого слова. Последняя строка позже удаляет этот пробел.
- Команда
s
в строке 3 ищет вхожденияi
в слове, заканчивающемся на ,o
и заменяет его наa
.t
Команда возвращается к метке,:a
чтобы повторить это для всехi
слов,o
заканчивающихся на . - Теперь пятая строка удаляет окончание
o
и еще одну петлю. Обратите внимание, что из слова, заканчивающегося наoo
, они оба будут удалены; неясно, желательно ли это.
Только для справок я использую sed
версию, поддерживающую o
опцию команды, s
которая означает только сохранение совпавшей части и отбрасывание остального. Также она знает \h
в замене, чтобы заменить содержимым удерживаемого пространства. Это делает задачу однострочной:
sed -E ':a;h;s/([[:alnum:]]*)o($|[^[:alnum:]])/\1\2/o;T;y/i/a/;x;s//\h/;ba'
решение2
АвкДля такого случая было бы точнее и гибче:
awk '{ for(i=1;i<=NF;i++)
if ($i~/o$/) { sub(/o$/,"",$i); gsub("i","a",$i) } }1' <<<"filo fililo felo fale"
Выход:
fal falal fel fale
АльтернативаПитонподход с использованием командной строки:
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
решение3
Я не уверен, возможно ли это сделать с помощью Python sed
(подозреваю, что, скорее всего, нет), но это очень легко сделать с помощью Python! Вот скрипт, который делает именно то, что вам нужно:
#!/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)
Вы можете запустить его так:
echo 'filo fililo felo fale' | python modify_strings.py
И он выдает следующий вывод (как и требовалось):
фал фалал фал фале
Если вы действительно хотите sed
участвовать, то вы, вероятно, можете получить то, что хотите, дополнив это небольшим скриптингом оболочки. Это может выглядеть примерно так bash
:
#!/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
Вы могли бы вызвать этот скрипт так:
bash modify-strings.bash filo fililo felo fale