sed를 사용하여 파일의 마지막 n 줄을 제거하는 방법


148

파일 끝에서 일부 n 줄 을 제거하고 싶습니다 . sed를 사용 하여이 작업을 수행 할 수 있습니까?

예를 들어 2에서 4까지 줄을 제거하려면

$ sed '2,4d' file

그러나 나는 줄 번호를 모른다. 나는 마지막 줄을 사용하여 삭제할 수 있습니다

$sed $d file

하지만 끝에서 n 줄 을 제거하는 방법을 알고 싶습니다 . sed 또는 다른 방법을 사용하여 방법을 알려주십시오.


2
@ arashkordi : 파일의 맨 아래가 아닌 줄 수를 사용합니다.
ams

에 관련 질문 슈퍼 유저 .
Thor

// 아마도 그 질문을 단순한 것보다 더 일반적인 것으로 바꾸는 것을 고려할 것입니다 sed.
Nathan Basanese

1
sed $d file오류를 반환합니다. 대신 $ d는 다음과 같이 따옴표 안에 있어야합니다.sed '$d' file
Akronix

답변:


221

에 대해 sed모르지만 다음과 head같이 할 수 있습니다 .

head -n -2 myfile.txt

19
단순화를 위해 +1 동등한 sed 명령은 추악합니다 : sed -e :a -e '$d;N;2,5ba' -e 'P;D' file( ,5마지막 5 줄).
Marc B

62
이 버전의 일부 버전에서는 작동 head하지만 표준 버전 은 아닙니다. 실제로, head주에 대한 표준 :The application shall ensure that the number option-argument is a positive decimal integer.
William Pursell

21
@WilliamPursell의 답변에 추가하려면 ... Mac OS 기본 셸에서는 작동하지 않습니다.
JDS

7
BSD는 아니지만 Linux에는 태그가 붙어 있습니다.
ams

3
때문에 마이너스 1, OSX에 더하여,이 Ubuntu14에 나를 위해 작동하지 않습니다 -head: illegal line count -- -2
마이클 듀런트

30

하드 코딩 n이 옵션 인 경우 순차적 호출을 사용하여 sed를 수행 할 수 있습니다. 예를 들어, 마지막 세 줄을 삭제하려면 마지막 한 줄을 세 번 삭제하십시오.

sed '$d' file | sed '$d' | sed '$d'

2
stdout에 덤프하지 않고 파일을 편집하기 위해 -i를 추가하면 나에게 도움이되었습니다.
WAF

27

로부터 나오지 한 라이너 :

# delete the last 10 lines of a file
sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # method 1
sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # method 2

당신이 찾고있는 것 같습니다.


@ 여기에서 10in 을 변경하여 파일에서 제거되는 행 수를 변경할 수 있습니다 .'$d;N;2,10ba'
Alexej Magura

1
@ AlexejMagura : 이전 버전의 답변에 대해 언급하고있었습니다.
Thor

22

재미 있고 간단 sed하며 tac해결책 :

n=4
tac file.txt | sed "1,$n{d}" | tac

노트

  • "쉘이 명령 에서 $n변수 를 평가하려면 큰 따옴표 가 필요합니다 sed. 작은 따옴표에서는 보간이 수행되지 않습니다.
  • tacA는 cat역 참조man 1 tac
  • {}에서 sed가 분리됩니다 $nd(하지 않을 경우, 보간 비 존재에 쉘 시도 $nd변수)

7
tacOSX에 대한 제한 없음
Michael Durrant

1
@MichaelDurrant port info coreutils|| brew info coreutils;
목소리

19

을 사용 sed하되 쉘이 수학을 수행 d하도록하고, 마지막 23 줄을 제거하기 위해 범위를 지정 하여 명령 을 사용하는 것을 목표로합니다 .

sed -i "$(($(wc -l < file)-22)),\$d" file

안쪽에서 바깥쪽으로 마지막 3 줄을 제거하려면 :

$(wc -l < file)

파일의 줄 수를 알려줍니다 : say 2196

왼쪽 또는 범위의 경우 마지막 23 행을 제거하려고합니다.

$((2196-22))

부여 : 2,174 쉘 해석이 후에 따라서 원래는 나오지 :

sed -i '2174,$d' file

-i내부 편집을 수행 하면 파일은 이제 2173 행입니다!

새 파일로 저장하려면 코드는 다음과 같습니다.

sed -i '2174,$d' file > outputfile

15

이것을 위해 머리 를 사용할 수 있습니다 .

사용하다

$ head --lines=-N file > new_file

여기서 N은 파일에서 제거하려는 행 수입니다.

원래 파일의 내용에서 마지막 N 줄을 뺀 내용이 이제 new_file에 있습니다.


8

완전성을 위해 솔루션을 추가하고 싶습니다. 나는 이것을 표준으로 끝내었다 ed.

ed -s sometextfile <<< $'-2,$d\nwq'

이것은 내부 편집을 사용하여 마지막 두 행 삭제 (그것이 비록 않습니다 에 임시 파일을 사용합니다 /tmp!)


5

매우 큰 파일을 실제로 제자리에 자르려면 truncate명령이 있습니다. 줄에 대해서는 모르지만 tail+ wc는 줄을 바이트로 변환 할 수 있습니다.

file=bigone.log
lines=3
truncate -s -$(tail -$lines $file | wc -c) $file

파일이 동시에 쓰여질 경우 명백한 경쟁 조건이 있습니다. 이 경우 사용하는 것이 더 나을 수 있습니다 head-파일의 시작 부분부터 바이트 수를 계산하므로 (마인 디스크 IO) 항상 줄 경계에서 잘립니다 (파일이 활발하게 작성되면 예상보다 많은 줄이 가능합니다).

truncate -s $(head -n -$lines $file | wc -c) $file

로그인에 실패하면 사용자 이름 대신 암호를 입력하십시오.

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure

4

이것은 당신을 위해 일할 수 있습니다 (GNU sed) :

sed ':a;$!N;1,4ba;P;$d;D' file

좋은. 결말 아포스트로피 ( ')를 놓쳤습니다 .
Thor

너무 늦은 의견에 대해 죄송하지만 시도하고 (내 AIX / posix에 추가) 마지막 줄을 제외한 모든 인쇄에 실패했습니다. 그것은 확실히 루프 A 이후 있도록 코드를 읽고, 내가 마지막 네 줄을 제거하는 방법을 이해하지 못하고, 명시 적 루프는 4 개 첫번째 라인에 d, D또는 PGNU가 나오지도하지 POSIX 버전에와. 다음 줄은 인쇄되지 D않고 작업 줄의 '끝'에 전달하지 않고 새 루프의 작업 버퍼에 보관합니다.
NeronLeVelu

@NeronLeVelu 프로그램은 4 줄의 창에서 패턴 공간으로 읽은 후 다음 줄을 추가하고 파일의 끝에 도달하여 나머지 줄을 삭제할 때까지 첫 줄을 인쇄합니다.
potong

@potong 예, GNU sed에서 테스트 D하고 반대 효과를 만든 후 posix가 언로드하는 라인 사이에 버퍼를 유지합니다 .
NeronLeVelu

4

위의 답변 대부분에는 GNU 명령 / 확장이 필요한 것 같습니다.

    $ head -n -2 myfile.txt
    -2: Badly formed number

약간 더 이식 가능한 솔루션의 경우 :

     perl -ne 'push(@fifo,$_);print shift(@fifo) if @fifo > 10;'

또는

     perl -ne 'push(@buf,$_);END{print @buf[0 ... $#buf-10]}'

또는

     awk '{buf[NR-1]=$0;}END{ for ( i=0; i < (NR-10); i++){ print buf[i];} }'

"10"은 "n"입니다.


2

여기에 대한 답변으로 sed 가이 응용 프로그램에 가장 적합한 도구는 아니라는 것을 이미 알게되었습니다.

그러나 나는 sed를 사용할 때 이것을 할 수있는 방법이 있다고 생각합니다. 아이디어는 EOF를 누르지 않고 읽을 수있을 때까지 공간을 유지하기 위해 N 줄을 추가하는 것입니다. EOF에 도달하면 보류 공간의 내용을 인쇄하고 종료하십시오.

sed -e '$!{N;N;N;N;N;N;H;}' -e x

위의 sed 명령은 마지막 5 줄을 생략합니다.


2

다음 명령을 시도하십시오 :

n = line number
tail -r file_name | sed '1,nd' | tail -r

이것이 어떻게 작동하는지 설명하십시오. 참고로 쉘 변수를 초기화하려면 공간이 없어야합니다 =.
codeforester

@codeforester 첫 줄은 내가 생각한 의견이었습니다. 그는 tail -r다른 사람들이 tac줄 순서를 바꾸는 데 사용 하고 마지막 n줄을 n첫 줄로 만듭니다.
Nicolas Melay

2

3 단계로 수행 할 수 있습니다.

a) 편집하려는 파일의 줄 수를 세십시오.

 n=`cat myfile |wc -l`

b) 해당 숫자에서 삭제할 줄 수를 뺍니다.

 x=$((n-3))

c) sed에게 그 줄 번호 ( $x)에서 끝까지 삭제 하도록 지시하십시오.

 sed "$x,\$d" myfile

나쁜 수학. 3 행을 삭제해야하는 경우 3에서 ADD 1을 뺍니다. 수학에서 파일에 10 행, 10-3 = 7이 있고 7 행에서 10 행, 즉 3 sed행이 아닌 4 행을 삭제 하는 데 사용 하는 경우
mathguy

1

총 라인 수를 가져 와서 wc -l <file>사용할 수 있습니다.

head -n <total lines - lines to remove> <file>


1

이렇게하면 마지막 3 줄이 제거됩니다 file.

for i in $(seq 1 3); do sed -i '$d' file; done;


1
큰 파일에는 너무 비싸므로 전체 파일을 n 번 읽고 다시 써야합니다! 그리고 많은 포크 sed.
codeforester

이것이 가장 효율적인 솔루션은 아니지만 가장 간단하고 이해하기 쉽습니다
Dharam

0

이 솔루션을 선호합니다.

head -$(gcalctool -s $(cat file | wc -l)-N) file

여기서 N 은 제거 할 행 수입니다.


0
sed -n ':pre
1,4 {N;b pre
    }
:cycle
$!{P;N;D;b cycle
  }' YourFile

posix 버전


0

마지막 4 줄을 삭제하려면

$ nl -b a file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//'   

약간 무거운 (특히 자원에서) 머리와 비교됩니다. 적어도 tac file | sed '1,4d' | tac정렬 후 접두사가 많은 리소스를 제거하기 때문에.
NeronLeVelu

@NeronLeVelu 당신 말이 맞지만 tac어떤 시스템 도 명령 이 없습니다 (예 : FreeBSD?)
mstafreshi

0

나는 이것을 생각해 냈습니다. 여기서 n은 삭제하려는 줄 수입니다.

count=`wc -l file`
lines=`expr "$count" - n`
head -n "$lines" file > temp.txt
mv temp.txt file
rm -f temp.txt

약간 우회전하지만 따라 가기 쉽다고 생각합니다.

  1. 메인 파일의 줄 수를 세어보세요
  2. 카운트에서 제거하려는 줄 수를 뺍니다.
  3. 임시 파일에 보관하고 저장할 줄 수를 인쇄하십시오.
  4. 기본 파일을 임시 파일로 교체
  5. 임시 파일을 제거

0

파일의 마지막 N 줄을 삭제하려면 동일한 개념을 사용할 수 있습니다

$ sed '2,4d' file

tail 명령과 함께 콤보를 사용하여 파일을 되돌릴 수 있습니다. N이 5 인 경우

$ tail -r file | sed '1,5d' file | tail -r > file

그리고이 방법은 head -n -5 file명령이 실행되지 않는 곳에서도 실행됩니다 (Mac에서와 같이!).


-2

이것은 마지막 12 줄을 제거합니다

sed -n -e :a -e '1,10!{P;N;D;};N;ba'

1
약간의 설명이 도움이 될 것입니다.
Richard Wiseman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.