좋은 방법
일반적으로 grep으로이 작업을 수행 할 수 없지만 다른 도구를 사용할 수 있습니다. AWK는 이미 언급되었지만 다음 sed
과 같이 사용할 수도 있습니다 .
sed -e '1p' -e '/youpattern/!d'
작동 방식 :
Sed 유틸리티는 각 라인에서 개별적으로 작동하여 각각에 지정된 명령을 실행합니다. 여러 -e
옵션을 지정하여 여러 명령을 가질 수 있습니다. 이 명령을 특정 행에 적용해야하는지 여부를 지정하는 범위 매개 변수를 사용하여 각 명령 앞에 붙일 수 있습니다.
"1p"는 첫 번째 명령입니다. p
일반적으로 모든 줄을 인쇄 하는 명령을 사용 합니다. 그러나 적용해야 할 범위를 지정하는 숫자 값 앞에 붙입니다. 여기서는 1
첫 번째 줄을 의미합니다. 더 많은 줄을 인쇄하려면 첫 줄 인쇄 위치, 마지막 줄 인쇄 x,yp
위치 를 사용할 수 있습니다 . 예를 들어 처음 3 줄을 인쇄하려면x
y
1,3p
다음 명령은 d
일반적으로 버퍼에서 모든 행을 삭제합니다. 이 명령 전에 우리는 yourpattern
두 /
문자 사이에 넣습니다 . 이것은 p
명령이 실행되어야하는 행을 주소 지정하는 다른 방법입니다 (먼저 명령 으로 수행 한 행을 지정하는 것이 었습니다 ). 이것은 명령이 일치하는 행에 대해서만 작동 함을 의미합니다 yourpattern
. 단, 명령 !
앞의 문자를 사용 d
하여 논리를 반전시킵니다. 이제 지정된 패턴과 일치 하지 않는 모든 줄을 제거합니다 .
마지막으로 sed는 버퍼에 남아있는 모든 행을 인쇄합니다. 그러나 버퍼에서 일치하지 않는 행을 제거하여 일치하는 행만 인쇄합니다.
요약하자면 첫 번째 줄을 인쇄 한 다음 패턴과 일치하지 않는 모든 줄을 입력에서 삭제합니다. 라인의 나머지 (그래서 전용 라인 인쇄 할 패턴과 일치를).
첫 줄 문제
주석에서 언급 했듯이이 접근법에는 문제가 있습니다. 지정된 패턴이 첫 번째 줄과도 일치하면 두 번 인쇄됩니다 ( p
명령에 따라 한 번, 일치 때문에 한 번). 우리는 이것을 두 가지 방법으로 피할 수 있습니다 :
다음에 1d
명령 추가 1p
. 이미 언급했듯이 d
command는 버퍼에서 행을 삭제하고 번호 범위로 범위를 지정합니다. 즉, 첫 번째 행만 삭제합니다. 따라서 명령은sed -e '1p' -e '1d' -e '/youpattern/!d'
1b
대신 명령을 사용합니다 1p
. 속임수입니다. b
command를 사용하면 레이블로 지정된 다른 명령으로 이동할 수 있습니다 (이렇게하면 일부 명령을 생략 할 수 있음). 그러나이 레이블이 지정되지 않은 경우 (예에서와 같이)이 명령은 줄 끝의 나머지 명령을 무시하고 명령 끝으로 이동합니다. 따라서 우리의 경우 마지막 d
명령은 버퍼 에서이 줄을 제거하지 않습니다.
전체 예 :
ps aux | sed -e '1b' -e '/syslog/!d'
세미콜론 사용
일부 sed
구현에서는 여러 -e
옵션 을 사용하는 대신 세미콜론을 사용하여 명령을 구분하여 입력을 절약 할 수 있습니다. 따라서 이식성에 신경 쓰지 않는다면 명령은입니다 ps aux | sed '1b;/syslog/!d'
. 그것은 적어도 작동 GNU sed
및 busybox
구현.
미친 길
그러나 grep 으로이 작업을 수행하는 미친 방법이 있습니다. 확실히 최적의 것은 아니며 학습 목적으로 만 게시하고 있지만 시스템에 다른 도구가없는 경우 예를 들어 사용할 수 있습니다.
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog'
작동 원리
먼저 -n
옵션을 사용 하여 각 줄 앞에 줄 번호를 추가합니다. 우리는 일치하는 모든 줄 .*
, 심지어 빈 줄 까지 숫자로 만들고 싶습니다 . 의견에서 제안한 것처럼 '^'도 일치시킬 수 있으며 결과는 동일합니다.
그런 다음 확장 정규식을 사용하므로 \|
OR로 작동 하는 특수 문자를 사용할 수 있습니다 . 따라서 줄이 1:
(첫 번째 줄)로 시작 하거나 패턴 (이 경우 해당 줄)을 포함 하면 일치합니다 syslog
.
줄 번호 문제
이제 문제는 출력에서이 못생긴 줄 번호를 얻는 것입니다. 이것이 문제라면 cut
, 다음과 같이 제거 할 수 있습니다 :
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog' | cut -d ':' -f2-
-d
옵션은 구분자를 -f
지정하고 인쇄하려는 필드 (또는 열)를 지정합니다. 따라서 모든 :
문자의 각 줄을 잘라 두 번째 및 모든 후속 열만 인쇄 하려고합니다 . 이렇게하면 구분 기호가있는 첫 번째 열이 효과적으로 제거되며 이것이 정확히 필요한 것입니다.
ack
이 유용하고perl
과거sed
에awk
, 등이 인기를 얻었던 이유는 무엇입니까 ?