파일 중간에 특정 줄을 표시하는 빠른 유닉스 명령?


206

서버와 내 유일한 로그 파일로 문제를 디버깅하려고하면 20GB 로그 파일입니다 (타임 스탬프조차도 없습니다! 사람들은 왜 사용합니까? System.out.println() 이 로깅으로 ?)

grep을 사용하여 347340107 행에서 살펴볼 파일 영역을 찾았습니다.

같은 일을하는 것 외에

head -<$LINENUM + 10> filename | tail -20 

... head로그 파일의 처음 347 백만 행을 읽어야하는 경우 콘솔에 347340100-347340200 행을 덤프하는 빠르고 쉬운 명령이 있습니까?

업데이트 grep이 일치하는 컨텍스트를 인쇄 할 수 있다는 것을 완전히 잊어 버렸습니다 ... 이것은 잘 작동합니다. 감사!


grep이 전체 파일을 검색해야한다고 생각합니다 .CPU를 덜 집중적으로 사용해야합니다.
ojblass

답변:


69

GNU-grep을 사용하면 말할 수 있습니다.

grep --context = 10 ...

7
보다 구체적으로 10 줄 전 : ​​grep -B 10 ... 또는 10 줄 뒤 : grep -A 10 ...
Boy Baukema

17
sed -n '<start>, <end> p'아래에서이 명령이 작동하지 않습니다.
Basav

5
일치하는 내용이 최상위 비트에 있어도 전체 파일을 처리하므로 실제로 원하는 결과 가 아닙니다 . 이 시점에서 머리 / 꼬리 또는 꼬리 / 머리 콤보가 훨씬 더 효과적입니다.
Sklivvz

3
요청 된 특정 을 출력하는 방법을 제공하지 않으므로 요청 된 질문을 전혀 만족시키지 않습니다 .
Chris Rasys

1
이것은 실제로 요청 된 것이 아닙니다. @ matt b, 왜이 대답을 받아들이지 않습니까?
user1271772

390

줄 번호를 알고 있지만 다른 정보가 없으면 다른 두 가지 해결책을 찾았습니다 .

20 ~ 40 행이 필요하다고 가정하면,

sed -n '20,40p;41q' file_name

또는

awk 'FNR>=20 && FNR<=40' file_name

6
+1 : 인쇄 후 종료하고 싶을 수도 있습니다. 파일이 실제로 큰 경우 성능상의 이점을 제공 할 수 있습니다.
jaypal 싱

awk 'NR> = 20 && NR <=
40'file_name

2
그런 다음 sed -n '20, 40p; 41q 'file_name을 종료하십시오.
Snigdha Batra

1
특히, 시작 및 끝 줄 번호입니다. 당신이 더 큰 파일의 경우는 '12345678,12345699p'이 될 것입니다
코드 Abominator

1
또한 @CodeAbominator의 의견에 41q따라 sed가 line 을 종료 하도록 지시 합니다 41.
Brice

116
# print line number 52
sed -n '52p' # method 1
sed '52!d' # method 2
sed '52q;d' # method 3,  efficient on large files 

큰 파일에 효율적인 방법 3

특정 라인을 표시하는 가장 빠른 방법


방법 3을 단일 행 대신 범위를 사용하도록 조정하는 방법을 찾으려고 노력하고 있지만 sed-foo가 작업에 달려 있지 않을까 걱정됩니다.
Xiong Chiamiov

9
@XiongChiamiov 1-500을 인쇄하기위한 sed -n '1,500p; 501q'는 어떻습니까?
Sam

3
처음 두 줄 / 방법이 비효율적 인 이유는 52 번 줄 이후까지 모든 줄을 계속 처리하기 때문입니다. 반면 # 3은 52 번 줄을 인쇄 한 후에 중지합니다.
flow2k

1
이 답변은 모든 논쟁이 무엇을하는지 설명하는 데 도움이됩니다.
Bram Vanroy

25

아니요, 파일은 주소를 지정할 수 없습니다.

텍스트 파일에서 줄 n 의 시작을 찾는 일정한 시간 방법은 없습니다 . 파일을 통해 스트리밍하고 개행을 계산해야합니다.

작업을 수행해야하는 가장 단순하고 빠른 도구를 사용하십시오. 나를 위해, 사용이 head만드는 훨씬 더 의미 grep후자는 방법이 더 복잡하기 때문에. 나는 " grep느리다" 라고 말하는 것이 아니라 실제로는 그렇지 않지만 head이 경우 보다 더 빠르면 놀랄 것 입니다. head기본적으로 버그입니다 .


2
줄의 너비가 바이트 단위로 고정되어 있지 않으면 파일 시작 부분에서 줄 바꿈 문자를 세지 않고 파일 포인터를 어디로 옮길 지 알 수 없습니다.
Joseph Lust

이것은 질문에 대한 답변을 제공하지 않습니다. 저자에게 비평을하거나 설명을 요청하려면 게시물 아래에 의견을 남겨주십시오.
exhuma

@exhuma 당신이 맞아요. 나는 다시 썼다. 7 년 전 저를 화나게했습니다. :)

20

이건 어떤가요:

tail -n +347340107 filename | head -n 100

나는 그것을 테스트하지 않았지만 그것이 효과가 있다고 생각합니다.


아니요. 테일의 버전 및 OS에 따라 일반적으로 tail의 마지막 KB는 256 개로 제한됩니다.
Antti Rytsölä

💪 yessire miller
dctremblay

13

난 그냥 들어가 선호 less하고

  • 입력 50%하여 파일의 중간으로 이동
  • 43210G 43210 행으로 이동
  • :43210 똑같이

그런 것들.

더 좋은 방법 : v해당 위치에서 편집을 시작하십시오 (vim에서!). 이제 vim동일한 키 바인딩이 있습니다.


12

먼저 파일을 이처럼 몇 개의 작은 파일로 분할했습니다

$ split --lines=50000 /path/to/large/file /path/to/output/file/prefix

그런 다음 결과 파일을 grep하십시오.


동의하면 로그를 해체하고 크론 작업을 만들어 제대로 수행하십시오. logrotate 또는 이와 유사한 것을 사용하여 너무 커지지 않도록하십시오.
Tanj

9

다음 ex과 같은 표준 Unix 편집기 (현재 Vim의 일부) 인 명령을 사용할 수 있습니다.

  • 단일 행을 표시합니다 (예 : 두 번째 행).

    ex +2p -scq file.txt

    해당 sed 구문 : sed -n '2p' file.txt

  • 라인 범위 (예 : 2-5 라인) :

    ex +2,5p -scq file.txt

    sed 구문 : sed -n '2,5p' file.txt

  • 주어진 줄부터 끝까지 (예 : 파일의 5 번째 끝까지) :

    ex +5,p -scq file.txt

    sed 구문 : sed -n '2,$p' file.txt

  • 여러 줄 범위 (예 : 2-4 및 6-8 줄) :

    ex +2,4p +6,8p -scq file.txt

    sed 구문 : sed -n '2,4p;6,8p' file.txt

위의 명령은 다음 테스트 파일로 테스트 할 수 있습니다.

seq 1 20 > file.txt

설명:

  • + 또는 -c 명령 뒤에-파일을 읽은 후 (vi / vim) 명령을 실행하십시오.
  • -s -자동 모드, 현재 터미널을 기본 출력으로 사용
  • q다음 -c은 편집기를 종료하는 명령입니다 ( !예 : 강제 종료를 위해 추가 -scq!) ( 예 :) .

7

행 번호를 100으로 읽는 경우

head -100 filename | tail -1

6

가져 오기 ack

우분투 / 데비안 설치 :

$ sudo apt-get install ack-grep

그런 다음 다음을 실행하십시오.

$ ack --lines=$START-$END filename

예:

$ ack --lines=10-20 filename

보낸 사람 $ man ack:

--lines=NUM
    Only print line NUM of each file. Multiple lines can be given with multiple --lines options or as a comma separated list (--lines=3,5,7). --lines=4-7 also works. 
    The lines are always output in ascending order, no matter the order given on the command line.

1
이것은 나에게 모든 대답 중 가장 직관적 인 구문을 가진 명령처럼 보입니다.
nzn

2019 년 1 월 10 일 버전 2.999_06부터 --lines매개 변수가 제거되었습니다.
화상

4

sed는 행을 계산하기 위해 데이터를 읽어야합니다. 바로 가기가 가능한 유일한 방법은 파일에서 컨텍스트 / 순서가 작동하는 것입니다. 예를 들어 고정 너비 시간 / 날짜 등이 추가 된 로그 라인이있는 경우 look unix 유틸리티를 사용하여 특정 날짜 / 시간에 대한 파일을 이진 검색 할 수 있습니다.


4

사용하다

x=`cat -n <file> | grep <match> | awk '{print $1}'`

일치하는 줄 번호를 얻을 수 있습니다.

이제 다음 명령을 사용하여 100 줄을 인쇄 할 수 있습니다

awk -v var="$x" 'NR>=var && NR<=var+100{print}' <file>

또는 "sed"도 사용할 수 있습니다

sed -n "${x},${x+100}p" <file>

일치하는 항목이 여러 개인 경우 "awk 'NR == 1 {print $ 1}"등을 사용하십시오.
Ramana Reddy

2

으로 sed -e '1,N d; M q'당신이 라인을 인쇄 할 수 있습니다 M.이를 통해 N + 1은 아마 조금 더 나은 다음이다 grep -C그것은 패턴 라인을 일치하려고하지 않는 한.


-e여기서는 선택 사항입니다.
flow2k

2

Sklivvz의 답변을 바탕으로 .bash_aliases파일에 넣을 수있는 멋진 기능이 있습니다. 파일 앞에서 인쇄 할 때 대용량 파일에 효율적입니다.

function middle()
{
    startidx=$1
    len=$2
    endidx=$(($startidx+$len))
    filename=$3

    awk "FNR>=${startidx} && FNR<=${endidx} { print NR\" \"\$0 }; FNR>${endidx} { print \"END HERE\"; exit }" $filename
}

1

A로부터 선 표시하려면 <textfile>해당로를 <line#>, 다만이 작업을 수행 :

perl -wne 'print if $. == <line#>' <textfile>

정규 표현식으로 여러 줄을 표시하는 더 강력한 방법을 원한다면 grep이 왜 그렇게 나쁜 생각인지 말하지 않을 것입니다.이 간단한 표현은 당신에게 범위를 보여줍니다. ~ 20GB 텍스트 파일을 처리 할 때 원하는 단일 패스 :

perl -wne 'print if m/<regex1>/ .. m/<regex2>/' <filename>

(팁 : 정규 표현식에 포함 /된 경우 m!<regex>!대신 비슷한 것을 사용하십시오)

<filename>일치하는 줄 <regex1>까지 일치하는 줄부터 시작하여 일치하는 줄을 포함하여 인쇄합니다 <regex2>.

몇 번의 조정만으로 더 강력한 기능을 만드는 방법을 알아 보려면 마법사가 필요하지 않습니다.

마지막으로 : 펄 (Perl)은 성숙한 언어이기 때문에 속도와 성능을 높이기 위해 많은 숨겨진 향상 기능이 있습니다. 이를 염두에두고 원래 큰 로그 파일, 텍스트, 데이터베이스 등을 처리하기 위해 개발되었으므로 이러한 작업을위한 확실한 선택입니다.


실제로, 하나 이상의 perl 명령을 실행하는 것이 말보다 더 복잡하고 2 + 프로그램을 함께 파이프 (페이지 아래로) 실행하면 더 많은 것을 입력했기 때문에 실제로 말하는 것 같습니다. 물 밖으로 날아 가지 않은 페이지 아래에 똑같이 복잡한 (또는 그 이상) 있기 때문에 당신이
읽어야하는 설명

사용자가 다양한 라인을 요청 했으므로 예제를 간단하게 조정할 수 있습니다.
Sklivvz

0

이 명령을 시도해 볼 수 있습니다.

egrep -n "*" <filename> | egrep "<line number>"

0

펄로 쉽게! 파일에서 1, 3, 5 행을 가져 오려면 / etc / passwd라고 말하십시오.

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd

1
당신은 awk로 쉽다고 말하지만 대신에 perl로 했습니까?
죄수 13

0

Ramana Reddy의 다른 답변 만 출력에 줄 번호를 추가 할 것을 제안했습니다. 다음은 필요한 줄 번호를 검색하고 출력 색상을 지정합니다.

file=FILE
lineno=LINENO
wb="107"; bf="30;1"; rb="101"; yb="103"
cat -n ${file} | { GREP_COLORS="se=${wb};${bf}:cx=${wb};${bf}:ms=${rb};${bf}:sl=${yb};${bf}" grep --color -C 10 "^[[:space:]]\\+${lineno}[[:space:]]"; }

코드가있는 답변은 삭제 플래그 만 표시되는 경향이 있습니다. 이것이 어떻게 문제를 해결하는지에 대한 논평을 추가 할 수 있습니까?
Graham
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.