파일에 다음이 포함되어 있는지 확인해야 합니다.특정 줄에 대한 특정 정규식발견되면 true(0 종료)를 반환하고, 그렇지 않으면 false를 반환합니다. 내가 너무 생각하고 있었을지도 모르지만, 내 시도는 조금 서투른 것으로 판명되었습니다. 해결책이 있는데 생각하지 못한 다른 해결책을 찾고 있습니다. Perl을 사용할 수도 있지만 꼭두각시 실행 주기 내에서 실행되므로 이를 가능한 한 "경량"으로 유지하고 싶습니다.
이 문제는 일반적입니다. RHEL6에서는 132에서 줄의 주석 처리를 해제하지 않는 한 터미널 너비를 80자로 제한하는 방식으로 화면이 패키지됩니다. 이 명령은 해당 줄이 수정되었는지 확인합니다.
awk 'NR==132 && /^#termcapinfo[[:space:]]*xterm Z0=/ {x=1;nextfile} END {exit 1-x}' /etc/screenrc
참고: 파일이 132줄 미만인 경우 false로 종료해야 합니다.
여기서는 도움이 될 것이라고 생각 sed
하지만 분명히 널 대체 및 분기와 같은 이상한 트릭을 수행해야 합니다. 그래도 배울 수 있는 sed 솔루션을 보고 싶습니다. 어쩌면 내가 간과하고 있는 다른 것들이 있을 수도 있습니다.
편집 1: nextfile
내 awk 솔루션에 추가됨
편집 2: 기준 편집 3: 다른 호스트(유휴). 편집 4: 각 실행을 최적화하기 위해 Gile의 awk 시간을 잘못 사용했습니다. 편집 5: 새로운 벤치
벤치마크
먼저 참고 사항: wc -l /etc/screenrc
예 216
. 라인이 존재하지 않는 경우 50,000회 반복(벽 시간으로 측정):
- 무작동: 0.545초
- 내 원래 awk 솔루션: 58.417
- 내 편집된 awk 솔루션(nextfile 사용): 58.364s
- Giles의 awk 솔루션: 57.578s
- 최적화된 Perl 솔루션 90.352s 아야!
Sed 132{p;q}|grep -q ...
솔루션: 61.259초- Cuonglm의
tail | head | grep -q
: 70.418s 아야! - Don_Christie's
head -nX |head -n1|grep -q
: 116.9s 우후! - Terdon의 이중 grep 솔루션: 65.127s
- John1024의 sed 솔루션:45.764초
고마워요 존, 고마워요 sed! 솔직히 말해서 Perl이 여기에 동급이라는 사실에 놀랐습니다. Perl은 시작 시 여러 공유 라이브러리를 로드하지만 운영 체제가 모든 라이브러리를 캐시하는 한 이는 파서 및 바이트 인코더에 따라 달라집니다. 먼 과거(perl 5.2?)에는 20% 더 느린 것으로 나타났습니다. 처음에 예상했던 대로 Perl은 느리지만 복사/붙여넣기 오류로 인해 Perl이 더 나은 것 같습니다.
벤치마킹 2부
실용적인 가치가 있는 가장 큰 구성 파일은 입니다 /etc/services
. 그래서 이 파일에 대한 벤치를 다시 실행했는데 변경할 줄은 파일 전체의 2/3였습니다. 총 행 수는 1100이었으므로 7220을 선택하고 그에 따라 정규 표현식을 수정했습니다(한 경우에는 실패하고 다른 경우에는 성공하도록, 워크벤치의 경우 항상 실패함).
- John의 sed 솔루션: 121.4s
- Christie의
{head;head}|grep
솔루션: 138.341s - Kangam의
tail|head|grep
솔루션:77.948초 - 내 awk 솔루션: 175.5s
답변1
GNU sed 사용:
sed -n '132 {/^#termcapinfo[[:space:]]*xterm Z0=/q}; $q1'
어떻게 작동하나요?
132 {/^#termcapinfo[[:space:]]*xterm Z0=/q}
132행에서 정규식을 확인합니다
^#termcapinfo[[:space:]]*xterm Z0=
. 종료가 발견되면q
기본 종료 코드는 0입니다. 파일의 나머지 부분은 건너뜁니다.$q1
마지막 줄에 도달하면
$
종료 코드 1: 을 사용하여 종료합니다q1
.
능률
파일의 132번째 줄을 읽을 필요가 없기 때문에 이 버전은 132번째 줄이나 파일의 끝에 도달하는 중 먼저 발생하는 즉시 종료됩니다.
sed -n '132 {/^#termcapinfo[[:space:]]*xterm Z0=/q; q1}; $q1'
빈 파일 처리
위 버전은 빈 파일에 대해 true를 반환합니다. 파일이 비어 있으면 명령이 실행되지 않고 sed가 기본 종료 코드 0으로 종료되기 때문입니다. 이러한 상황을 방지하려면 다음을 수행하세요.
! sed -n '132 {/^#termcapinfo[[:space:]]*xterm Z0=/q1; q}'
여기서 sed 명령은 필요한 문자열이 발견되지 않는 한 코드 0으로 종료되고, 해당 문자열이 발견되면 코드 1로 종료됩니다. 앞의 !
내용은 쉘에게 이 코드를 뒤집어 우리가 원하는 코드로 돌아가도록 지시합니다. !
모든 POSIX 쉘은 이 수정자를 지원합니다. 이 버전은 빈 파일에서도 작동합니다. (모자팁: G-Man)
답변2
POSIX 도구 상자 사용:
tail -n +132 </etc/screenrc | head -n 1 | grep -q pattern
답변3
awk에서 이 작업을 더 효율적으로 수행할 수 있습니다. 관련 줄에 도달하면 종료하세요.
awk 'NR==132 {if (/^#termcapinfo[[:space:]]*xterm Z0=/) found=1; exit}
END {exit !found}' /etc/screenrc
아니면 할 수 있습니다GNU sed 사용(그러나 휴대용 sed에서는 종료 코드를 지정할 수 없습니다.)
또는 도구를 함께 그룹화하는 Unix 철학을 사용할 수 있습니다. 즉, head
원하는 줄을 사용 및 추출 tail
하고 에 전달합니다 grep
.
</etc/screenrc tail -n +132 | head -n 1 |
grep -q '^#termcapinfo[[:space:]]*xterm Z0='
또는 sed를 사용하여 필요한 줄을 추출할 수 있습니다.
</etc/screenrc sed -n '32 {p; q;}' |
grep -q '^#termcapinfo[[:space:]]*xterm Z0='
(이 두 가지 모두 빈 줄과 너무 짧은 파일로 동일한 결과를 원한다는 사실에 의존합니다.)
head
이러한 작은 파일의 경우 가장 빠른 방법은 단일 도구를 사용하는 것입니다. 여러 프로그램을 실행하는 오버헤드가 전용 도구(예 : , 및 )를 사용하여 tail
얻을 수 있는 성능 향상 보다 크기 때문입니다 sed
. 행 132000000을 원한다면 그것으로 시작하는 것이 tail -n +132000000
아마도 다른 것보다 빠를 것입니다.
답변4
.perl
다음을 수행할 수 있습니다.
#!/usr/bin/env perl
use strict;
use warnings;
open ( my $input_fh, '<', "/etc/screenrc" ) or die $!;
while ( <$input_fh> ) {
if ( $. == 132
and m/^#termcapinfo[[:space:]]*xterm Z0=/ ) {
exit 0;
}
}
exit 1;
라이너로 압축할 수 있습니다.
perl -ne 'exit 0 if $. == 132 and m/^#termcapinfo[[:space:]]*xterm Z0=/ END { exit 1 }'