如何使(sed)正则表达式替换一个字符的所有出现,同时删除最后一个字符?

如何使(sed)正则表达式替换一个字符的所有出现,同时删除最后一个字符?

我正在努力解决以下问题。我在 Mac 终端中使用这样的命令来测试我的正则表达式:

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

我正在尝试创建一个正则表达式:

  • 当且仅当一个单词以字母“o”结尾时,那么:
  • 删除这个词尾的“o”
  • 将单词中所有出现的字母“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/ $//'
  • 在第一行中,我在末尾添加了一个空格,因此我们可以像对待任何单词结尾一样对待行结尾。最后一行稍后删除该空格。
  • 第 3 行中的命令在以 结尾的单词中s搜索 的出现并将其替换为。该命令循环回到标记,以对所有结尾单词中的所有单词重复此操作。ioat:aio
  • 现在第五行删除了结尾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对于这种情况会更加准确和灵活:

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命令行方法:

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

我不确定这是否可行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参与其中,那么您可能可以通过使用一些 shell 脚本来增强它来获得您想要的东西。这可能类似于以下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

相关内容