sed正規表現で単語末尾の文字を削除しようとしています

sed正規表現で単語末尾の文字を削除しようとしています

私は正規表現と sed の初心者で、単純な正規表現を作成しようとしています。単語の最後の文字が 'o' の場合は、その文字を削除したいのです。

  • 入力文字列: Hello Hello
  • 予想される出力: 地獄地獄

良いニュース: 文字列の末尾にある 'o' を削除できます。

$ echo 'Hello Hello' |sed 's/\(.*\)o/\1/g'
Hello Hell
$ echo 'Hello Hello' |sed 's/\(.*\)o$/\1/g'
Hello Hell

悪いニュース: 文字列の前の単語から削除することはできません。考えられるすべてのアンカー シンボルでこれを試しました。結果は、単語の末尾の 'o' が削除されませんでした。

$ echo 'Hello Hello' |sed 's/\(.*\)o\b/\1/g'
Hello Hello
$ echo 'Hello Hello' |sed 's/\(.*\)o\>/\1/g'
Hello Hello
$ echo 'Hello Hello' |sed 's/\(.*\)o\W/\1/g'
Hello Hello
$ echo 'Hello Hello' |sed 's/\(.*\)o\s/\1/g'
Hello Hello

私が何を間違っているのかを教えて、正気を取り戻すのを手伝ってもらえませんか?

更新: 私のマシンは他の人のマシンとは異なる結果を生成するという明確な印象を受けます。私は Macbook のターミナル ウィンドウを使用しています。これについて何かわかる方がいらっしゃいましたら、教えてください。

答え1

echo 'Hello Hello' | sed 's/o$//'

あなたのよりも私には役立つようです

echo 'Hello Hello' | sed 's/\(.*\)o$/\1/g'

あなたの質問では、出力は

echo 'Hello Hello' | sed 's/\(.*\)o\b/\1/g'

でしたHello Helloが、私にとってはそうですHello Hell。これを修正すると

echo 'Hello Hello' | sed 's/\([^o]*\)o\b/\1/g'

しかし

echo 'Hello Hello' | sed 's/o\b//g'

私にはその方が良いように思えます。

答え2

単語の末尾のを削除するとo、単語文字と非単語文字 (または EOL) の間の ao が削除されます。つまり、次のようになります。

sed -r 's/(\w)o(\W|$)/\1\2/g'

答え3

単語の区切り文字が正しくないのではないかと思いますspace。次のようなものを試してみてください。

$ echo hello hello | sed -e 's/o / /g;s/o$//'
hell hell

.この例の問題は、 and,やその他の単語区切り文字についても、同じことを行う必要があることです。などoの別の特定の文字が続くものに一致します。何らかの理由で、これは EOL では機能しないため、 を含む別の検索文字列を追加します。例:[]o[ \.,]$;

$ echo hello hello, hello. toot hello | sed -e 's/o\([ \.,]\)/\1/g;s/o$//'
hell hell, hell. toot hell
$ echo $SHELL
/bin/bash
$ sed --version
sed (GNU sed) 4.4
$ set | grep IFS
IFS=$' \t\n'

答え4

私は思いつく限りのアンカーシンボルすべてでこれを試しました。

アンカーの問題ではなく、アスタリスクとの貪欲な一致があるという事実です。\(.*\)o表現は一致しますできるだけ長い文字列、だからそれはすべてを食べるでしょう最後 oo以前のものとも一致する可能性があります。

しかし、何かをキャプチャして戻すのは無意味なので、\(.*\)と を\1完全に削除するだけで済みます。

したがって、これらは (少なくとも GNU sed では)o単語の末尾の 's を削除します。

sed 's/o\>//g' 
sed 's/o\b//g' 

もちろん、これは文字列の末尾にのみ適用されます。

sed 's/o$//g' 

oこれにより、 とそれに続く非単語文字 (たとえば、 の後のスペースHello)が削除されます。

sed 's/o\W//g' 

が/または をsedサポートしていない場合は、別の方法を使用する必要があります。これは、英数字以外の文字または行末に一致します。\<\>\bo

$ echo "jello, jello" | sed -E -e 's/o([^[:alnum:]]|$)/\1/g'
jell, jell

これは、たとえばsedOS X/macOS に付属する で動作します。


*Perlの正規表現では、またはに疑問符を追加する+ことで非貪欲にすることができます。そうすると、最短可能な文字列:

echo "jello, jello" | perl -pe 's/(.*?)o/$1/g'
jell, jell

関連情報