Linux에서 텍스트 파일의 특정 줄을 표시하는 방법은 무엇입니까?


85

나는 모두가 유용한 리눅스 cmd를 줄 유틸리티를 알고 생각 head하고 tail. head파일의 첫 번째 X 줄을 인쇄 할 수는 tail있지만 동일한 작업을 수행하지만 파일 끝을 인쇄합니다. 파일 중간을 인쇄하는 좋은 명령은 무엇입니까? middle --start 10000000 --count 20(10'000'000에서 10'000'010 번째 줄까지 인쇄) 와 같은 것 .

큰 파일을 효율적으로 처리 할 수있는 것을 찾고 있습니다. 나는 노력 tail -n 10000000 | head 10했고 끔찍하게 느립니다.


답변:


111
sed -n '10000000,10000020p' filename

다음과 같이 약간 속도를 높일 수 있습니다.

sed -n '10000000,10000020p; 10000021q' filename

이러한 명령에서이 옵션 -nsed"패턴 공간의 자동 인쇄 억제"를 유발 합니다. p명령 "인쇄 [S] 현재 패턴 공간"및 q명령은 "즉시 더 이상의 입력을 처리하지 않고 [S]를 나오지도 스크립트를 종료 ..."따옴표는 출신 sed man페이지 .

그건 그렇고, 당신의 명령

tail -n 10000000 filename | head 10

파일 의 에서 천만 번째 줄에서 시작 하는 반면 "중간"명령은 처음부터 천만 번째에서 시작 하는 것처럼 보입니다 .

head -n 10000010 filename | tail 10

문제는 가변 길이 줄을 가진 정렬되지 않은 파일의 경우 모든 프로세스가 줄 바꿈을 계산하는 파일을 거쳐야한다는 것입니다. 바로 가기 방법은 없습니다.

그러나 파일이 정렬되거나 (예를 들어 타임 스탬프가있는 로그 파일) 고정 길이 줄이있는 경우 바이트 위치를 기준으로 파일을 찾을 수 있습니다. 로그 파일 예제에서 내 파이썬 스크립트 * 와 같이 일정 시간 동안 이진 검색을 수행 할 수 있습니다 . 고정 레코드 길이 파일의 경우 정말 쉽습니다. 당신 linelength * linecount은 파일에 문자를 추구 합니다.

* 나는 그 스크립트에 또 다른 업데이트를 게시하는 것을 의미합니다. 요즘 어쩌면 나는 그것에 대해 갈 것입니다.


다음은 sedCharles middle기능 버전입니다 middle() { local s=$1 c=$2; shift 2; sed -n "$s,$(($s + $c -1))p; $(($s + $c))q" "$@"; }.. 여러 개의 파일 인수, 공백이있는 파일 이름 등을 처리합니다. 여러 개의 파일은 sed일반적으로 하는 것과 같은 방식으로 분류 된 것처럼 함께 처리됩니다 (따라서 중간 1000 100 file1 file2는 첫 번째 파일의 끝에서 처음으로 확장됩니다) 첫 번째 줄이 1100 줄 미만인 경우 두 번째 줄).
Dennis Williamson

: 내 이전 코멘트의 기능은 파일 이름 매개 변수를 호출 할 수 있습니다 middle startline count filename또는 여러 개의 파일 이름 : middle startline count file1 file2 file3또는 리디렉션 : middle startline count < filename: 또는 파이프의 some_command | 중간 startline의 count` 또는cat file* | middle startline count
데니스 윌리엄슨

sed 명령에서`는 '가 아니어야합니까? 백틱으로 작동시킬 수는 없지만 작은 따옴표로 잘 작동합니다.
Ian Hunter

@beanland : 예, 오타입니다. 나는 그것을 고쳤다. 감사.
Dennis Williamson

1
@ kev : 내 대답에 약간의 설명을 추가했습니다.
Dennis Williamson

28

나는 다음과 같은 용도를 발견했다. sed

sed -n '10000000,+20p'  filename

누군가에게 유용하기를 바랍니다!


Dennis가 제안한 마지막 행 인수에 대한 대안이 있다는 것을 아는 것이 좋습니다 sed -n.
user3123159

사용법 예 : extract_lines(){sed -n "$1,+$2p" <file>}stdout에 씁니다.
user3123159

4

여기가 처음으로 게시됩니다! 어쨌든 이것은 쉽다. file.txt라는 파일에서 8872 행을 가져오고 싶다고 가정 해 봅시다. 방법은 다음과 같습니다.

고양이 -n file.txt | grep '^ * 8872'

이제 문제는이 후 20 줄을 찾는 것입니다. 이것을 달성하기 위해 당신은

고양이 -n file.txt | grep -A 20 '^ * 8872'

주변 또는 이전 행에 대해서는 grep 매뉴얼의 -B 및 -C 플래그를 참조하십시오.


기술적으로 정확하고 합리적인 크기의 파일로 만드는 재미있는 방법이지만 포스터가 요구하는 크기의 파일로 작업 할 때의 효과에 대해 궁금합니다.
Jenny D

여러 줄 : cat -n file.txt | 그렙 "^ \ S \ + (10 \ | (20) \ | 30) \ S \ +"
제프리 나이트

cat -n file.txt | grep '^ *1'오른쪽에 1을 가진 모든 줄을 산출하십시오. 이 기술로 라인 1을 출력하는 방법은 무엇입니까? 나는 -n 1.을 할 수 있지만 grep을 사용하는 방법을 알고 있습니까?
Sean87

1

데니스의 sed 답변은 갈 길입니다. 그러나 bash에서 head & tail 만 사용하십시오.

중간 () {head -n $ [$ 1 + $ 2] | 꼬리 -n $ 2; }

이것은 첫 $ 1 + $ 2 라인을 두 번 스캔하므로 Dennis의 답변보다 훨씬 나쁩니다. 그러나 당신은 그것을 사용하기 위해 sed 편지를 모두 기억할 필요는 없습니다 ....


$[...]적어도 Bash에서는 사용 이 더 이상 사용 되지 않습니다. 또한 파일 매개 변수가 없습니다.
Dennis Williamson

@ Dennis : 누락 된 매개 변수가 없습니다 :에 따라 stdin에서 이것을 사용해야합니다 middle 10 10 < /var/log/auth.log.
Charles Stewart

1

특정 범위의 행을 얻으려면 다음 명령을 사용하십시오.

awk 'NR < 1220974{next}1;NR==1513793{exit}' debug.log | tee -a test.log

여기 debug.log는 줄 부족으로 구성된 내 파일이며 1220974 줄 번호에서 1513793 줄을 test.log 파일로 인쇄하는 데 사용되었습니다. 라인 범위를 캡처하는 데 도움이되기를 바랍니다.


serverfault.com/a/641252/140016 과 동일한 답변 입니다. 공감.
사슴 사냥꾼

같은 대답이 아닙니다. 파일을 계속 스캔하는 대신 마지막 줄을 인쇄 한 후 실제로 중단되므로 대용량 파일의 경우 더 빠릅니다.
공포증

0

루비 oneliner 버전.

ruby -pe 'next unless $. > 10000000 && $. < 10000020' < filename.txt

누군가에게 유용 할 수 있습니다. Dennis와 Dox가 제공 한 'sed'가있는 솔루션은 더 빠르기 때문에 매우 좋습니다.


0

'nl'을 사용할 수 있습니다.

nl filename | grep <line_num>


0

줄 번호 줄을 알고 있다면 파일에서 줄 1, 3 및 5를 가져 오려면 / etc / passwd라고 말하십시오.

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

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