web-dev-qa-db-ja.com

ファイルの先頭に行/テキストを追加する方法

次のサンプルファイルがあります。

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をファイルに追加することです。

しかし、これはエレガントな解決策ではありません。

4
yael

POSIX指定のファイルエディタex を使用した比較的エレガントなソリューション---これはany任意を処理するという意味で少なくともエレガントです内容特定の形式(末尾のバックスラッシュ)または特定の形式の欠如に依存するのではなく。

printf '0r headerfile\nx\n' | ex file-with-contents

これにより、exfile-with-contentsが開き、最上部のheaderfileの内容全体が読み込まれ、変更されたバッファがfile-with-contentsに保存されます。

パフォーマンスが深刻な問題であり、ファイルが巨大な場合、これは適切な方法ではない可能性がありますが、(a)prependデータをファイルに出力する一般的な方法はなく、(b)ありません/etc/servicesファイルを頻繁に編集することは期待できません


少しすっきりした構文(実際にこれをコーディングする方法):

printf '%s\n' '0r headerfile' x | ex file-with-contents

servicesの始まりがheader全体と正確に一致するかどうかをチェックするコードのより複雑な、しかし収束的なビット、バイトごとに、そしてIF NOTが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

GNU cmpの「-n」オプションを使用した、はるかに単純なバージョン:

cmp -sn "$(wc -c <header)" header services ||
  printf '%s\n' '0r header' x | ex services

もちろん、どちらもPARTIALの一致をチェックするほどスマートではありませんが、推測は本質的に関与するため、単純なワンライナーの能力をはるかに超えています。

6
Wildcard

通常、あなたはそれをします。ファイルは単なるバイトのシーケンスであるため、ファイルの先頭に行を追加することは難しいため、既存のデータを先に移動して新しいデータ用のスペースを作る必要があり、そのための直接的な方法はありません(少なくとも標準的な方法はありません)。理論的には、可変長レコードに基づくファイルシステムを想像するかもしれません。そこでは、最初または既存のレコードの間に新しいレコードを追加できますが、実際にはそうではありません。

一部のファイルシステムはデータのブロックを移動できますが、それらは固定サイズのブロックであるため、行が可変長であるテキストファイルにはあま​​り使用されません。

sed -iPerl -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

ただし、挿入コマンドを生成したり、追加する行ごとにバックスラッシュを追加したりするのも、洗練されていません。

4
ilkkachu

わかりましたコメント以外に答えを書くことにしました。

次のように、isedコマンドを使用できます。

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
Weijun Zhou

別のアプローチ:ほとんどのLinuxディストリビューションで利用可能な moreutils パッケージのspongeを使用して、次のこともできます

$ 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

同じ結果を達成するため。

0
mindriot

結果を達成するために、sed one linerの下で使用されます。テストしたように、それはうまくいきました

疑問があれば教えてください

 sed '1s/.*/\n&/g' examplefile| sed '1r file2.txt'  | sed '1d'

examplefile ===>その入力ファイル

file2.txt ===>これは、examplefileの先頭に追加する必要があるコンテンツを含むファイルです

0