파이프를 사용하지 않고 파일의 마지막 n 줄에서 단어를 찾기 위해 grep을 사용하고 싶습니다.
grep <string> filename
파일 이름에서 문자열을 검색할 수 있습니다. 그러나 파일의 마지막 N 줄에서 문자열을 검색하고 싶습니다. 파이프를 사용하지 않고 검색하는 명령이 있습니까?
답변1
쉘이 이를 지원하는 경우( zsh
, , , bash
의 일부 구현 ksh
) 다음을 사용할 수 있습니다.프로세스 교체
grep <pattern> <(tail -n5 yourfile.txt)
여기서 -n5는 마지막 5개 라인을 가져오는 것을 의미합니다.
비슷하게,
grep <pattern> <(head -n5 yourfile.txt)
yourfile.txt의 처음 5줄이 검색됩니다.
설명하다
간단히 말해서, 대체된 프로세스는 grep이 기대하는 파일로 가장합니다. 프로세스 대체의 장점 중 하나는 diff
이 예에 표시된 것처럼 여러 명령의 출력을 다른 명령에 대한 입력으로 사용할 수 있다는 것입니다.
diff -y <(brew leaves) <(brew list)
이렇게 하면 파이프(
|
) 문자가 제거되지만 각 대체 문자는 실제로파이프라인 생성1 .
1 적어도 ksh93
Linux에서는|
아니요파이프를 사용하지만 소켓 쌍을 사용하십시오.프로세스 교체open
파이프를 사용하십시오(소켓은 불가능하므로).
$ ksh93 -c '읽기링크 <(:)' 파이프: [620224] $ ksh93 -c ': 읽기 링크 /proc/self/fd/0' 소켓: [621301]
답변2
n=$some_num
{ head -n"$(($(wc -l <in)-n))" >/dev/null
grep 'match your string'
} <in
불행하게도 줄 수를 얻으려면 파일을 완전히 읽어야 합니다. wc
그렇지 않으면 파일에 몇 줄이 있는지, 얼마나 큰지 명확하지 않기 때문입니다 $n
. 그 외에 이것은 매우 성능이 좋은 솔루션이어야 합니다 <in
.lseek()
유능한문서.
먼저 행 수를 구하고 $n
그 수를 뺍니다. head
stdin에서 해당 행을 읽고 결과를 작성합니다 /dev/null
. 그 후에 남은 것은 $n
stdin의 입력 행 수와 사용자 grep
의 패턴뿐입니다.
기술적으로 이것은 속임수입니다.예명령의 파이프는 으로 대체됩니다 wc
. 이를 무시해도 됩니다.
그런데 또 다른 접근 방식은 다음과 같습니다.
{ grep "-m$n" 'some pattern near yours' >/dev/null
grep 'your pattern'
} <in
...GNU와 함께 grep
. 목표 패턴 근처 어딘가에 나타나는 다른 패턴을 가질 수 있다면 grep
$n
실제로 파이프 없이도 그렇게 할 수 있습니다.
나는 w/ 를 고수하려고 노력하고 있지만 grep
어쨌든 sed
여기에 해결책이 있습니다. 아래 파이프라인은 입력 전용입니다. grep
줄 번호 앞에 추가하는 것 외에는 전혀 관련되지 않으므로 어떤 번호인지 확인할 수 있습니다. 이 모든 것은 예시 사례에만 적용됩니다. sed
모든 종류의 명명된 파일이나 표준 입력에 스크립트만 사용할 수 있으며 $pat
적절한 $n
설정을 사용하면 작동합니다.
사실 저는 경기를 고정시킬 수 없는 게 싫어서 이것을 다시 썼습니다. 이것은조금느림 - 눈에 띄지는 않지만 여전히 매우 빠르지만 버퍼링된 모든 후행 라인에 대해 후행 패턴 공간을 모두 잘라내고 버퍼의 첫 번째 라인을 격리합니다. 이렇게 하면 모든 일반 앵커 표현식이 예상대로 작동합니다.
pat=man n=40
man man |
grep -n ''|
sed -e:B -e'${/^\n/D' \
-eh -e's/\n.*//' \
-e"/$pat/p;x" \
-e\} -e'$D;N;$bB' \
-e"$n,$ D;bB"
648: /etc/man_db.conf
649: man-db configuration file.
651: /usr/share/man
652: A global manual page hierarchy.
654: /usr/share/man/index.(bt|db|dir|pag)
657: /var/cache/man/index.(bt|db|dir|pag)
661: apropos(1), groff(1), less(1), manpath(1), nroff(1), troff(1), whatis(1),
662: zsoelim(1), setlocale(3), manpath(5), ascii(7), latin1(7), man(7), cat-
663: man(8), mandb(8), the man-db package manual, FSSTND
680: developing and maintaining man-db.
다음은 파일에 대한 또 다른 예입니다.
pat=. n=15
seq 100 >nums
sed -e:B -e'${/^\n/D' \
-eh -e's/\n.*//' \
-e"/$pat/p;x" \
-e\} -e'$D;N;$bB' \
<nums -e"$n,$ D;bB"
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
답변3
왜 파이프를 피해야 합니까?
실제로 파이프 사용을 피하려면 다음 두 가지 명령을 실행해야 합니다.
tail -N filename > filename.tmp
grep "string" filename.tmp
(when N is the last number of lines)
답변4
awk
약간의 도움을 받으면 이 작업을 수행 할 수 있습니다 .
$ N=8
$ awk -v start_line="$(( $(wc -l < alphabet) - N + 1 ))" 'NR>=start_line && /e/' alphabet
sierra
whiskey
yankee
$
e
마지막 8줄에 포함된 모든 줄 찾기병음 알파벳. 이것의 단점은 전체 입력 파일을 두 번 읽는다는 것입니다.