bash에서 다음으로 시작하고 끝나지 않는 줄을 파일에서 제거합니다.

bash에서 다음으로 시작하고 끝나지 않는 줄을 파일에서 제거합니다.

특정 문자나 문자 집합으로 시작하는 줄을 삭제하는 방법에 대한 sed 예제를 많이 읽었으며 그다지 어렵지는 않지만 이 예제를 해독할 수는 없습니다. 파일에서 문자 "i"로 시작하고 ".conf"로 끝나지 않는 모든 줄을 삭제하고 싶습니다.

다음은 예시 목록입니다.

include /usr/local/choops/users/2488.conf
include /usr/local/cho
include /usr/local/choops/users/2492.conf
i
incl

위의 예에서 삭제해야 할 3줄은 다음과 같습니다.

include /usr/local/cho
i
incl

그것들은 불완전하고 거기에 있을 수 없습니다.

StackExchange, StackOverflow 및 기타 다양한 포럼에서 본 예제의 몇 가지 변형을 시도했지만 올바르게 이해할 수 없는 것 같습니다. 내가 시도한 것은 다음과 같습니다.

sed -i '/^i.*[^\.conf]$/d' /usr/local/choops/users/main.conf

sed -i '/^i.\*\[^\\.conf\]$/d' /usr/local/choops/users/main.conf

sed -i '/^i.*[^.conf]$/d' /usr/local/choops/users/main.conf

여기서 main.conf는 위에 표시된 대로 .conf 파일 세트를 나열하는 파일입니다. 나는 이것이 너무 복잡하지 않을 것이라고 생각했지만 이 명령 중 어느 것도 나에게 작동하지 않는 것 같습니다. 다양한 소스와 sed에 대한 이해를 바탕으로 명령을 구축했습니다. 어떤 도움이라도 대단히 감사하겠습니다. 매우 혼란스럽습니다.

다음은 내가 원하는 것과 반대이지만 간단하다고 생각합니다.

sed -i 's/i.*.conf//' main.conf

답변1

동시에 충족되어야 하는 두 가지 조항이 있습니다("i로 시작", ".conf로 끝나지 않음"). 출력에서 행을 제외하려면 각 절을 개별적으로 테스트한 다음 함께 결합해야 합니다.

입력 예("i"로 시작하지 않는 추가 행 추가):

$ cat input.txt 
include /usr/local/choops/users/2488.conf
this line doesn't begin with i
include /usr/local/cho
this line doesn't begin with i but does end in .conf
include /usr/local/choops/users/2492.conf
i
incl

그리고 perl:

$ perl -ne 'print unless (/^i/ && ! /\.conf$/)' input.txt 
include /usr/local/choops/users/2488.conf
this line doesn't begin with i
this line doesn't begin with i but does end in .conf
include /usr/local/choops/users/2492.conf

그리고 sed:

$ sed -ne '/^i/ {/\.conf$/!d;};p' input.txt 
include /usr/local/choops/users/2488.conf
this line doesn't begin with i
this line doesn't begin with i but does end in .conf
include /usr/local/choops/users/2492.conf

또는 @seshoumara가 제안한 것처럼 (아마도 더 나을 것입니다):

sed -e '/^i/ {/\.conf$/!d;}' input.txt

세 가지 버전 모두 출력에서 ​​원하지 않는 줄을 제거하고 다른 모든 내용을 인쇄합니다.

답변2

줄이 "i"로 시작하면 true이고 줄이 ".conf"로 끝나지 않으면 true라는 두 가지 조건이 있는 것 같습니다. 한 번에 검색하는 대신 두 번에 걸쳐 검색하세요.

sed -i '/^i/{/\.conf$/!d}' /usr/local/choops/users/main.conf

아니면 그 반대라면 부정하세요.

sed -i '/^i.*\.conf$/!d' /usr/local/choops/users/main.conf

점은 이스케이프 처리되어야 합니다. 그렇지 않으면 임의의 문자를 나타내는 정규 표현식이 됩니다.

실제로 시도하고 있는 "[^abc]" 정규식은 "a", "b" 또는 "c"가 아닌 단일 문자를 의미합니다. "j" 또는 "z"일 수 있습니다. 이 정규식이 무엇과 일치하든 여전히 단일 문자입니다. 마지막으로 "[]" 또는 "[^]"의 문자는 정규식 의미를 가질 수 없으며 단지 리터럴 문자 목록일 뿐이므로 "."는 항상 점을 의미하므로 이스케이프할 필요가 없습니다. 그러나 // 또는 s///에서는 상황에 따라 이스케이프를 원합니다.

답변3

문자 "i"로 시작하고 ".conf"로 끝나지 않는 파일의 모든 줄을 삭제하고 싶습니다.

  • A"라고 하자 .문자로 시작하다i"
  • B"라고 하자 .다음으로 끝남.conf"

사용부울 논리"A이고 B가 아님" 조건과 일치하는 행을 삭제한다고 말할 수 있습니다.

A . B'

또한 이를 "{ A 또는 B가 아님 }의 부정"으로 다시 작성할 수 있습니다.

( A' + B'' )' = ( A' + B )'

이를 사용하면 grep이것을 다음과 같이 바꿀 수 있습니다.유지하다(삭제하는 대신) 표현식과 일치하는 행은 다음과 같습니다.

( A' + B )

코드에서는 이렇게 됩니다.

grep -E '^[^i]|\.conf$'

실제로는 전혀 문자로 시작하지 않는 줄(즉, 공백)도 고려해야 합니다.

grep -E '^[^i]|\.conf$|^$'

예제 파일을 사용하면 다음 줄을 유지할 수 있습니다.

include /usr/local/choops/users/2488.conf
include /usr/local/choops/users/2492.conf

내부 편집(연기 및 거울)에는 일반적인 규칙이 적용되므로 직접 적용합니다.

grep ... file >file.tmp &&
    mv -f -- file.tmp file
rm -f -- file.tmp

답변4

begin with the letter "i" and DO NOT end with ".conf"awk를 사용하면 지정한 일치 요구 사항을 삭제하려는 줄을 식별하는 코드로 간단히 변환할 수 있습니다.

$ awk '/^i/ && !/\.conf$/' file
include /usr/local/cho
i
incl

그런 다음 유지하려는 행을 얻으려면 조건을 무효화하십시오.

$ awk '!(/^i/ && !/\.conf$/)' file
include /usr/local/choops/users/2488.conf
include /usr/local/choops/users/2492.conf

원하는 경우 다음과 같이 단축할 수 있습니다.드모건의 법칙도착하다:

$ awk '!/^i/ || /\.conf$/' file
include /usr/local/choops/users/2488.conf
include /usr/local/choops/users/2492.conf

관련 정보