![如何使(sed)正则表达式替换一个字符的所有出现,同时删除最后一个字符?](https://linux22.com/image/122084/%E5%A6%82%E4%BD%95%E4%BD%BF%EF%BC%88sed%EF%BC%89%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%9B%BF%E6%8D%A2%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E7%9A%84%E6%89%80%E6%9C%89%E5%87%BA%E7%8E%B0%EF%BC%8C%E5%90%8C%E6%97%B6%E5%88%A0%E9%99%A4%E6%9C%80%E5%90%8E%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%EF%BC%9F.png)
我正在努力解决以下问题。我在 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
搜索 的出现并将其替换为。该命令循环回到标记,以对所有结尾单词中的所有单词重复此操作。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对于这种情况会更加准确和灵活:
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