次のサンプルファイルがあります。
tcpmux 1/tcp # TCP port service multiplexer
tcpmux 1/udp # TCP port service multiplexer
rje 5/tcp # Remote Job Entry
rje 5/udp # Remote Job Entry
echo 7/tcp
echo 7/udp
discard 9/tcp sink null
discard 9/udp sink null
systat 11/tcp users
systat 11/udp users
daytime 13/tcp
daytime 13/udp
qotd 17/tcp quote
qotd 17/udp quote
msp 18/tcp # Message send protocol (historic)
msp 18/udp # Message send protocol (historic)
chargen 19/tcp ttytst source
chargen 19/udp ttytst source
ファイルの先頭に次の行を追加するにはどうすればよいですか?
# The latest IANA port assignments can be gotten from
# http://www.iana.org/assignments/port-numbers
# The Well Known Ports are those from 0 through 1023.
# The Registered Ports are those from 1024 through 49151
# The Dynamic and/or Private Ports are those from 49152 through 65535
#
# Each line describes one service, and is of the form:
#
# service-name port/protocol [aliases ...] [# comment]
これにより、ファイルは次のように表示されます。
# The latest IANA port assignments can be gotten from
# http://www.iana.org/assignments/port-numbers
# The Well Known Ports are those from 0 through 1023.
# The Registered Ports are those from 1024 through 49151
# The Dynamic and/or Private Ports are those from 49152 through 65535
#
# Each line describes one service, and is of the form:
#
# service-name port/protocol [aliases ...] [# comment]
tcpmux 1/tcp # TCP port service multiplexer
tcpmux 1/udp # TCP port service multiplexer
rje 5/tcp # Remote Job Entry
rje 5/udp # Remote Job Entry
echo 7/tcp
echo 7/udp
discard 9/tcp sink null
discard 9/udp sink null
systat 11/tcp users
systat 11/udp users
daytime 13/tcp
daytime 13/udp
qotd 17/tcp quote
qotd 17/udp quote
msp 18/tcp # Message send protocol (historic)
msp 18/udp # Message send protocol (historic)
chargen 19/tcp ttytst source
chargen 19/udp ttytst source
簡単な解決策は、元のファイルをにコピーし、ファイルにfile.bck
新しい行を追加してからファイルにfile.bck
追加することです。
しかし、これはエレガントな解決策ではありません。
答え1
以下を使用する比較的エレガントなソリューションPOSIX固有のファイルエディタex
-少なくとも、この意味ではエレガントこれが処理するでしょうどのすべてのコンテンツ特定の形式(末尾のバックスラッシュ)に依存したり、特定の形式がないわけではありません。
printf '0r headerfile\nx\n' | ex file-with-contents
その後、 が開き、file-with-contents
最上位の内容全体を読み取り、変更されたex
バッファが再び保存されます。headerfile
file-with-contents
パフォーマンスが深刻な問題でファイルが大きい場合、この方法は適切ではありませんが、(a)高性能のための普遍的な方法はありません。プレフィックス/etc/services
データをファイルに保存して(b)ファイルを編集できないようです。それ頻繁に。
ややクリーンな構文(実際にコーディングした方法):
printf '%s\n' '0r headerfile' x | ex file-with-contents
services
以下は、最初の内容全体が正確に一致するかどうかをバイト単位で確認しheader
、一致しない場合はその内容header
全体を前に追加し、services
変更を保存するより複雑ですが収束的なコードです。
これはPOSIXと完全に互換性があります。
dd if=services bs=1 count="$(wc -c < header)" 2>/dev/null |
cmp -s - header ||
printf '%s\n' '0r header' x |
ex services
cmp
GNUの "-n"オプションを使用するより簡単なバージョン:
cmp -sn "$(wc -c <header)" header services ||
printf '%s\n' '0r header' x | ex services
もちろん、これらのどれも部分的な一致を確認するほどスマートではありませんが、本質的に推測が含まれているので、単純な一行アプローチの機能をはるかに超えています。
答え2
通常はそうします。ファイルは単なるバイトのシーケンスなので、ファイルに行を追加することは困難です。したがって、新しいデータのためのスペースを確保するために既存のデータを前に移動する必要があり、直接的な方法はありません(少なくとも標準的な方法ではありません)。理論的には、最初または既存のレコードの間に新しいレコードを追加できる可変長レコードベースのファイルシステムを想像することもできますが、実際にはそうではありません。
一部のファイルシステムはデータブロックを移動できますが、固定サイズのブロックなので、行の長さが可変のテキストファイルにはあまり使用されません。
sed -i
あるいは、同じ操作を実行しても、perl -i
この理由で後ろから一時ファイルを生成します。
したがって、エレガントであるかどうかにかかわらず、以下を選択します。
cat prefix data > data.new && mv data.new data
数行の場合(GNU sedで)、次のものを使用できます。
sed -i.bak -e '1i first prefix line' -e '1i second prefix line' data
しかし、挿入コマンドを生成したり追加したいすべての行にバックスラッシュを追加したりすることはあまりエレガントではありません。
答え3
まあ、私はコメントで答えを書くことにしました。
i
次のコマンドを使用できますsed
。
sed -i '1i \
# The latest IANA port assignments can be gotten from\
# http://www.iana.org/assignments/port-numbers\
# The Well Known Ports are those from 0 through 1023.\
# The Registered Ports are those from 1024 through 49151\
# The Dynamic and/or Private Ports are those from 49152 through 65535\
#\
# Each line describes one service, and is of the form:\
#\
# service-name port/protocol [aliases ...] [# comment]' file
これはGNU用ですsed
。 Macではsed
使用する必要がsed -i '' -e ...
ありますが、POSIXではsed
内部で簡単に行う方法はありません。
答え4
他の方法:sponge
使用その他のユーティリティパッケージはほとんどのLinuxディストリビューションで利用でき、これも可能です。
$ cat - file.txt | sponge file.txt
# The latest IANA port assignments can be gotten from
# http://www.iana.org/assignments/port-numbers
# The Well Known Ports are those from 0 through 1023.
# The Registered Ports are those from 1024 through 49151
# The Dynamic and/or Private Ports are those from 49152 through 65535
#
# Each line describes one service, and is of the form:
#
# service-name port/protocol [aliases ...] [# comment]
cat
これは、再現可能な標準入力(-
)と元のファイル(file.txt
)を結合し、結合された出力にパイプし、sponge
結果を同じファイルに書き換えるために使用されます。その後、ヘッダーを端末に貼り付けますCtrl+D
。
または、すでにヘッダーを別のファイルに保存している場合は、次のものを使用できます。
cat header.txt file.txt | sponge file.txt
同じ結果を得てください。