如何使(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

相關內容