不明な行数のパターンマッチングや「...の最後の項目を置き換える」などのいくつかの問題では、-z
GNUオプションがsed
本当に役に立つ可能性があります。同じ移植性をどのように取得できますか?
例: ファイルがあります。
yellow, green,
blue, black, purple,
orange,
white, red, brown
are some colours
ファイルの最後のコンマをに置き換えたいですand
。カンマがどの行にあるのか、行のどこにあるのかわかりません。 GNUで私はsed
できる
sed -z 's/\(.*\),/ \1 and/'
希望の出力を得る
yellow, green,
blue, black, purple,
orange,
white, red and brown
are some colours
POSIXで実行できる移植可能な方法でこれをどのように実行できますかsed
?
答え1
純粋なPOSIXでは、sed
すべての行を直接貼り付ける必要があります。一部の人はN
ループ内でこれを行いますが、最も簡単な方法は次のパターンを使用して予約済みスペースに追加することですH;1h;$!d;x
。
H
各行を予約済みスペースに追加します。残念ながら、最初の行を追加すると、バッファの先頭に改行文字が追加されます。1h
改行を防ぐために、最初の行の予約済みスペースを上書きします。$!d
最後の行を除くすべての行の処理は終了します。予約済みスペースに保存されるため、印刷する必要はありません。x
最後の行以降にのみ実行され(他のすべての行では追加のd
コマンド処理が停止します)、予約済みスペースとパターンスペースは変更されますx
。したがって、このコマンドの後は、予約済みスペースに収集されたファイル全体がパターンスペースに存在します。-z
GNUを選択してくださいsed
。もちろん、g
代わりに使用することもできますが、x
これによりコピー量が増えるため、x
速度が速くなります。
したがって、この例のスクリプトは次のようになります。
sed 'H;1h;$!d;x;s/\(.*\),/\1 and/'
参考にしてください非常に大きなファイルの場合はRAMを大量に使用するため、これらのファイルを処理することはお勧めできません。
答え2
sedは、単一の文字列に対して単純なs / old / new操作を実行するために使用されます。 s、g、p(-nを含む)以外の構文を使用するほとんどすべての場合と確かに「空間予約」について話す場合は、間違ったツールを使用していることです。このようなs / old / newよりも複雑な操作の場合は、代わりにawkを使用する必要があります。以下は、UNIXシステム上のすべてのシェルでawkで動作し、ファイル全体をメモリに保存せず、テキストで他の操作を実行したい場合は調整が簡単です。
$ cat tst.awk
/,/ { printf "%s", prev; prev="" }
{ prev = prev $0 ORS }
END {
if ( match(prev,/.*,/) ) {
prev = substr(prev,1,RLENGTH-1) " and" substr(prev,RLENGTH+1)
}
printf "%s", prev
}
$ awk -f tst.awk file
yellow, green,
blue, black, purple,
orange,
white, red and brown
are some colours
ファイル全体をメモリに入れて、次の不思議なルーンを書くことで、awkで簡単にこれを行うことができます。
$ awk '{r=r$0 ORS} END{h=r;sub(/,[^,]+$/,"",h);sub(/.*,/,"",r);printf "%s and%s",h,r}' file
yellow, green,
blue, black, purple,
orange,
white, red and brown
are some colours
しかし、ポイントはsedとは異なり、それを必要としないということです。