정규식 문자열을 사용하여 일치 항목이 포함된 첫 번째 줄 앞의 모든 줄을 어떻게 삭제할 수 있습니까? 예를 들어 이것을 어떻게 변경할 수 있습니까?
lost
load
linux
loan
linux
다음을 입력하세요:
linux
loan
linux
나는 시도했다:
echo "lost
load
linux
loan
linux" | sed -e 's/.*^li.*$//g'
그러나 아무것도 변경하지 않고 다음을 반환합니다.
lost
load
linux
loan
linux
일치하는 항목이 없을 때 아무 것도 출력하지 않도록 작동하기를 원합니다.
답변1
단방향 POSIXly:
$ echo "lost
load
linux
loan
linux" | sed -e/linux/\{ -e:1 -en\;b1 -e\} -ed
또는 더 짧게:
sed -n '/linux/,$p'
더 짧게:
sed '/linux/,$!d'
짧은 버전보다 긴 버전을 선호하는 이유를 궁금해하는 독자를 위해 긴 버전은 파일의 나머지 부분에 대한 I/O만 수행하는 반면, 범위를 사용하면 두 번째 주소가 regex인 경우 성능이 저하되고 정규식은 다음을 시도합니다. 필요한 것 이상으로 일치시킵니다.
고려하다:
$ time seq 1000000 | sed -ne '/^1$/{' -e:1 -en\;b1 -e\}
=====
JOB sed -e '/^1$/,$d'
87% cpu
0.11s real
0.10s user
0.00s sys
그리고:
$ time seq 1000000 | sed -e '/^1$/,/1000000/d'
=====
JOB sed -e '/^1$/,/1000000/d'
96% cpu
0.24s real
0.23s user
0.00s sys
두 버전의 차이점을 확인할 수 있습니다. 복잡한 정규식의 경우 이는 큰 차이를 만듭니다.
답변2
이는 명확하게 수행하기 쉽습니다 awk
.
echo "lost
load
linux
loan
linux" | awk '
/^li/ { found = 1 }
found { print }'
이는 found
임의로 선택한 자체 설명 이름을 가진 변수입니다. 프로그램이 정규식과 일치하는 입력 줄을 발견하면 설정됩니다. (변수의 초기 기본값은 0 또는 FALSE와 기능적으로 동일한 null입니다.) 따라서 입력 줄은 ^li
패턴 일치 이전이 아닌 이후에 인쇄됩니다. linux
패턴을 찾고 플래그를 설정하는 명령문 뒤에 조건부 인쇄 문이 오기 때문에 입력의 세 번째 줄(첫 번째 줄)을 인쇄합니다 . 네 번째 줄(줄)부터 인쇄를 시작하려면뒤쪽에첫 번째 linux
줄) 두 명령문의 순서를 반대로 바꾸면 됩니다.
정규식과 일치하는 입력 줄이 없으면 플래그가 설정되지 않으며 아무 것도 인쇄되지 않습니다.
앞서 말했듯이 플래그 변수의 이름은 임의적입니다. f
필요한 경우 더 짧은 이름(예: )을 사용할 수 있습니다. 그리고 { print }
기본 동작이므로 생략해도 됩니다. 따라서 명확성이 중요하지 않다면 위의 내용을 다음과 같이 단축할 수 있습니다.
echo "lost
load
linux
loan
linux" | awk '/^li/{f=1}f'
답변3
다른 두 가지 awk 솔루션:
둘 다 found
첫 번째 정규식 일치를 볼 때 플래그를 설정하고 해당 플래그가 설정되면 인쇄합니다.
echo "lost
load
linux
loan
linux" | awk 'BEGIN {found = 0} {if (found || $0 ~ /linux/) {found = 1; print}}'
이것은 약간 길지만 found
플래그를 다시 설정하지는 않습니다.
echo "lost
load
linux
loan
linux" | awk 'BEGIN {found = 0} {if (found) {print} else if ($0 ~ /linux/) {found = 1; print}}'
답변4
당신은 그것을 사용할 수 있습니다전임자배치 모드에서 파일을 직접 편집합니다. (실제로 파일을 변경하기 전에 출력 파일이 무엇인지 확인하고 싶다면 . 로 바꾸세요 x
. %p
)
printf '%s\n' 'a' 'linux' '.' '1,/linux/-1d' '$d' 'x' | ex -s file
a
,linux
, write는.
끝에 한 줄을 추가합니다.linux
1,/linux/-1d
간격 [파일의 첫 번째 줄, 첫 번째 앞의 첫 번째 줄 ]linux
에서 줄을 삭제합니다.$d
1단계에서 수동으로 삽입한 행을 삭제합니다.x
변경사항을 작성하고 종료합니다.
보다 직접적인 접근 방식(참조:편집 기록의 첫 번째 버전) 일치하는 항목이 없으면 파일은 변경되지 않은 상태로 유지됩니다. 이렇게 하면 필요에 따라 파일이 지워집니다(따라서 이상한 1단계).
$ cat file1
lost
load
linux
loan
linux
$ printf '%s\n' a linux . 1,/linux/-1d '$d' x | ex -s file1
$ cat file1
linux
loan
linux
$ cat file2
lost
load
loan
$ printf '%s\n' a linux . 1,/linux/-1d '$d' x | ex -s file2
$ cat file2 #file2 is empty