大文字と小文字を区別しない検索とsedへの置き換え


83

SEDを使用してログファイルからテキストを抽出しようとしています。あまり問題なく検索と置換を行うことができます。

sed 's/foo/bar/' mylog.txt

ただし、検索で大文字と小文字を区別しないようにします。私がグーグルで検索iしたところ、コマンドの最後に追加するとうまくいくようです。

sed 's/foo/bar/i' mylog.txt

ただし、これによりエラーメッセージが表示されます。

sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'

ここで何が問題になっていますか、どうすれば修正できますか?


2
sedのコピーを更新してみてください。Isedのコピーでは使用できない可能性のあるGNU拡張機能です。
Lazer 2010

4
EDIT:(。、アップルのドキュメントに反しをOS X上でsedの別の答えが示されているように、大文字と小文字を区別しないマッチングをサポートしていません)私はOPはOS X上での作業はしない答えを受け入れたとして、OS Xの資格を通じて打た
danorton 2013年

1
@danorton:ありがとう。Appleのドキュメントが、実装が提供しない何かを約束しているという感覚を以下の私の答えから導き出した場合:man sed実装と一貫性があります-大文字と小文字を区別しないマッチングについての言及はありません(実際にはサポートされていません)。そうでないことを主張する文書を見つけた場合は、お知らせください。
mklement0 2014

1
@ mklement0、はい、申し訳ありませんが、私は訂正されたままです。Appleのドキュメントでは、sedの大文字と小文字を区別しないマッチングについては何も主張していません。
danorton 2014

1
FWIW、BSDバージョンにOS Xが付属しているツールのGNUバージョンは、さまざまなパッケージマネージャーから入手できます。Homebrewを介してgプレフィックス付きのテキストユーティリティの完全なスイートをインストールしているので、ストックバージョンにない機能を使用しgsedたりgdate、必要なときに使用したりできます。
マークリード

回答:


73

アップデート:以降でMacOSのビッグサー(11.0) sedサポートしI、大文字と小文字を区別しないマッチングのためのフラグを、当該コマンドは、今(BSDが作業をする必要がありますので、sedそのバージョンを報告しませんが、あなたが一番下にある日付で行くことができますmanあるべきページ、March 27, 2017またはより最近の); 簡単な例:

# BSD sed on macOS Big Sur and above (and GNU sed, the default on Linux)
$ sed 's/ö/@/I' <<<'FÖO'
F@O   # `I` matched the uppercase Ö correctly against its lowercase counterpart

注:(I大文字)はフラグの文書化された形式ですがi、同様に機能します。

同様に、始まるMacOSのビッグサー(11.0)は awk、今あるロケール対応awk --version報告しなければならない20200816以上、最近):

# BSD awk on macOS Big Sur and above (and GNU awk, the default on Linux)
$ awk 'tolower($0)' <<<'FÖO'
föo  # non-ASCII character Ö was properly lowercased

以下は、Catalina(10.15)までのmacOSに適用されます。

明確にするために:macOSでは、BSDの実装sedであり、 大文字と小文字を区別しないマッチングをサポートしていません。信じがたいことですが、本当です。以前は受け入れ答え自体が示し、GNUの sedコマンドは、理由のその地位を獲得したperlコメントで述べたベースのソリューション。

そのPerlソリューションをUTF-8を介して外国文字でも機能させるには、次のようなものを使用します。

perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo"
  • -C 現在のロケールがUTF-8ベースであると想定して、ストリームとファイルのUTF-8サポートをオンにします。
  • -Mutf8解釈するにはPerlを指示するソースコードを(この場合は、文字列が渡さUTF-8など-pe) -これはより冗長の短い同等である-e 'use utf8;'.おかげで、マーク・リード

(注ことを使用すると、awkいずれかのオプションではない、としてawkMacOSで(すなわち、BWKのAWKBSDのawkは)完全にロケールを全く知らないように見える-そのtolower()およびtoupper()機能は、(外国の文字を無視し、sub()/gsub()開始する場合、鈍感フラグを持っていませんと))


POSIX標準sedとの関係に関する注記awk

BSDはsedawkその機能をPOSIXsedおよび POSIXawk仕様で義務付けられているものに制限します、GNUの対応物はさらに多くの拡張機能を実装します。


ロケールを修正するには:blogs.agilefaqs.com/2014/01/12/…–
Eduardo Cuomo

69

編集者注:このソリューションは、GNU sedにのみ適用されるため、macOSでは(そのままでは)機能しませんが、macOSにはBSD が付属していsedます。

「I」を大文字にします。

sed 's/foo/bar/I' file

2
これも見て、試してみましたが、それでも同じエラーメッセージが表示されます。
クレイグウォーカー

15
BSDsedには多くの制限があるようです。その場合は、PERL(つまり、perl -pe's / foo / bar / i ')でこれを行います。
ウェズリーライス

3
OS X Lionのデフォルトのインストールでは、次のエラーが発生します。sed:1: "s / foo / bar / I":代替コマンドのフラグが
Ben Clayton

13
I接尾辞は、携帯型の使用ではありませんsed。POSIXsedは、驚くほど制限されている基本正規表現(BRE)のみを使用します。大文字と小文字を区別しないマッチングは言うまでもなく、+\{1,\}代わりに使用する必要があります)もサポートしていません。sedでそれを行う唯一のポータブルな方法は、のようなものをチェックすることです/[hH][eE][lL][lL][oO]/。これはしばしば非現実的です。
edam 2014年

5
それ/gI以外の場合は、最初の試合で動作する必要があります。
Faheem Mitha 2014

25

sedMac OS Xでの別のgsed回避策は、MacPortsまたはHomeBrewからインストールしてから、エイリアスを作成することsed='gsed'です。


gsed "s / a / b / Ig"は機能します、ありがとう!なぜ良い答えが反対票を獲得する必要があるのですか?
マティアスM

3
この答えは素晴らしいです。使用は、brew install gnu-sedその後、私の〜/ .bash_profileをして、コメントを追加エイリアスに行ってきました。おかげ@davmat
ThinkBonobo

8
行う方が良いbrew install gnu-sed --with-default-names-これはデフォルトを上書きしますsed
Mar0ux 2016年

5

sedのよくある質問アドレス密接に関連大文字と小文字を区別しない検索。a)sedの多くのバージョンがフラグをサポートしており、b)sedで行うのは厄介なので、awkまたはPerlを使用する必要があることを指摘しています。

しかし、POSIX sedでそれを行うために、彼らは3つのオプションを提案しています(ここでの置換に適合):

  1. 大文字に変換し、元の行をホールドスペースに格納します。ただし、これは置換では機能しません。元のコンテンツは印刷前に復元されるため、大文字と小文字を区別しない一致に基づいて行を挿入または追加する場合にのみ適しています。

  2. たぶん可能性がに限定されているFOOFoofoo。これらはによってカバーすることができます

     s/FOO/bar/;s/[Ff]oo/bar/
    
  3. 可能なすべての一致を検索するには、各文字に角かっこ式を使用できます。

     s/[Ff][Oo][Oo]/bar/
    

pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.htmlは、あなたが移植性のsedで何ができるかである
D.Shawley

@ D.Shawleyそれは答えの何にも矛盾していませんよね?または、公式仕様にリンクしてコンテキストを追加しますか?私はそれを答えに加えることができます。
ベンヤミン

Wここで矛盾するものはありません。誰かがPOSIXを参照しているのを見て、リンクを追加したいと思っていました。ここでの回答の大部分は、sedの「非標準」macOS実装を忙しく嘆いていて、私を悩ませていました。
D.Shawley

@ D.Shawley今すぐ仕様へのリンクを追加しました:)
ベンヤミン

3

最初にパターンマッチングを行う場合、たとえば、

/pattern/s/xx/yy/g

次にI、パターンの後に次のように配置します。

/pattern/Is/xx/yy/g

例:

echo Fred | sed '/fred/Is//willma/g'

戻りますwillma; がないI場合は、文字列をそのまま返します(Fred)。


2
MacOで私が得るもの:sed: 1: "/fred/Is//willma/g": invalid command code I
Chris F Carroll

良いヒント。複雑な検索での使用方法は次のとおりsed -r '/'"$PATTERN"'/I,${s//'$YELLOW'&'$NO_COLOR'/g;b};$q3'です。テキストを印刷し、パターン(大文字と小文字を区別しない)が見つかった場合は、テキストを黄色(ansiカラー)で強調表示します。見つからない場合-リターンの終了コード3
ノーム・マノス

1

Mac版はsed少し制限があるようです。これを回避する1つの方法は、次の使用可能なバージョンを持つLinuxコンテナー(Docker経由)を使用することですsed

cat your_file.txt | docker run -i busybox /bin/sed -r 's/[0-9]{4}/****/Ig'

17
これは特に凶悪なことです。誰かがこれを真剣に検討している場合でも、GNUsedをローカルにインストールするだけです。
ocodo 2017年

やり過ぎですが、知っておくと便利な一般的なアプローチです!
YvesgereY

0

私にも同様のニーズがあり、これを思いついた:

このコマンドは、単にすべてのファイルを検索します。

grep -i -l -r foo ./* 

これはthis_shell.shを除外し(コマンドをthis_shell.shというスクリプトに入れた場合)、出力をコンソールにティーして何が起こったかを確認し、見つかった各ファイル名でsedを使用してテキストfooをbarに置き換えます:

grep -i -l -r --exclude "this_shell.sh" foo ./* | tee  /dev/fd/2 | while read -r x; do sed -b -i 's/foo/bar/gi' "$x"; done 

変更されていないファイルのすべてのタイムスタンプを変更するのが好きではなかったので、この方法を選択しました。grepの結果をフィードすると、ターゲットテキストを含むファイルのみを表示できます(したがって、パフォーマンス/速度も向上する可能性があります)

使用する前に、必ずファイルをバックアップしてテストしてください。一部の環境では、スペースが埋め込まれたファイルでは機能しない場合があります。(?)


0

以下を使用して、すべてのオカレンスを置き換えます。sed's / foo / bar / gI 'mylog.txt


大文字をカバーするstackoverflow.com/a/4412964/4294399を参照してくださいI。また、グローバルな置き換えについては質問されていないため、これが実際に質問に答えるとは思いません。
Calculuswhiz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.