파일 시작 부분에 줄/텍스트를 추가하는 방법

파일 시작 부분에 줄/텍스트를 추가하는 방법

다음과 같은 샘플 파일이 있습니다.

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다음 수정된 버퍼가 다시 저장됩니다.headerfilefile-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

cmpGNU 의 "-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

동일한 결과를 얻으십시오.

관련 정보