k
私は単語の最初のインスタンスだけを変更したいと思います。
どうすればいいですか?
例えば。ファイルにfoo.txt
「linux」という単語が100回含まれているとします。
最初の50項目を交換するだけです。
ベストアンサー1
sed
以下の最初の部分では、行で最初のk回発生する項目を変更する方法について説明します。 2番目の部分は、表示される行に関係なく、ファイル内の最初のk個の項目のみを変更することによってこのアプローチを拡張します。
ライン中心ソリューション
標準sedには、1行目からk番目に表示される単語を置き換えるコマンドがあります。たとえば、3の場合k
:
sed 's/old/new/3'
または、すべての項目を次のように置き換えることができます。
sed 's/old/new/g'
これらのどれもあなたが望むものではありません。
GNUは、sed
k番目の発生とすべての後続のケースを変更する拡張機能を提供します。たとえば、kが3の場合:
sed 's/old/new/g3'
これらを組み合わせて、好きなことをすることができます。最初の3つの項目を変更するには:
$ echo old old old old old | sed -E 's/\<old\>/\n/g4; s/\<old\>/new/g; s/\n/old/g'
new new new old old
ここでwhere\n
は一行には決して現れないので便利です。
説明する:
3つの代替コマンドを使用しますsed
。
s/\<old\>/\n/g4
これは、4番目とそれ以降のすべての項目
old
を\n
。\<
単語の始まりと\>
終わりを一致させるための拡張正規表現機能。これにより、完全な単語のみが一致します。拡張正規表現には-E
オプションが必要ですsed
。s/\<old\>/new/g
最初の3つの項目だけを保持すると、
old
すべて置き換えられますnew
。s/\n/old/g
4番目と残りのすべての発生は最初のステップ
old
に置き換えられます。\n
これにより元の状態に復元されます。
非GNUソリューション
GNU sedを使用できず、の最初の3つの項目をに変更するには、次の3old
つのコマンドをnew
使用しますs
。
$ echo old old old old old | sed -E -e 's/\<old\>/new/' -e 's/\<old\>/new/' -e 's/\<old\>/new/'
new new new old old
k
この方法は数字が小さい場合はうまく機能しますが、大きな数字に拡張するとうまく機能しませんk
。
GNU以外の一部のsedはセミコロンを使用したコマンドの結合をサポートしていないため、ここの各コマンドには独自の-e
オプションがあります。sed
単語の境界記号\<
とをサポートしていることを確認することもできます\>
。
ファイル中心のソリューション
sedにファイル全体を読み、交換を実行するように指示できます。たとえば、old
BSD スタイルを使用して sed の最初の 3 つの項目を置き換えるには、次のようにします。
sed -E -e 'H;1h;$!d;x' -e 's/\<old\>/new/' -e 's/\<old\>/new/' -e 's/\<old\>/new/'
sed コマンドはH;1h;$!d;x
ファイル全体を読み込みます。
上記はGNU拡張を使用していないため、BSD(OSX)sedで動作する必要があります。このアプローチには、sed
長い行を処理するためのメソッドが必要です。 GNUはsed
大丈夫でしょう。 GNU以外のバージョンを使用している人は、sed
長い行を処理する能力をテストする必要があります。
g
GNU sedを使用すると、上記のトリックをさらに一歩進めることができますが、最初の3つの項目を置き換えることができます\n
。\x00
sed -E -e 'H;1h;$!d;x; s/\<old\>/\x00/g4; s/\<old\>/new/g; s/\x00/old/g'
このアプローチはスケーラビリティが高く、k
規模も大きくなります。しかし、\x00
元の文字列にはないとします。\x00
bash文字列に文字を入れることは不可能なので、これは通常安全な仮定です。