다음과 같은 샘플 파일이 있습니다.
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
동일한 결과를 얻으십시오.