특정 문자나 문자 집합으로 시작하는 줄을 삭제하는 방법에 대한 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