답변:
에서 awk
당신이 무엇이든 필드 분리를 설정할 수 있습니다. 로 설정하면의 C
발생 횟수만큼 +1 필드가 표시됩니다 C
.
따라서 awk -F'C' '{print NF}' <<< "C1C2C3"
당신이 얻는 다면 4
: CCC
3 C
초로 구성 되므로 4 개의 필드로 구성됩니다.
C
정확히 한 번 발생하는 줄을 제거하려고합니다 . 이것을 고려하여 귀하의 경우 정확히 두 개의 C
필드 가있는 줄을 제거하고 싶을 것 입니다. 따라서 그냥 건너 뛰십시오.
$ awk -F'C' 'NF!=2' file
DTHGTY
HYTRHD
HTCCYD
awk 'BEGIN { print "FS={" FS"}","OFS={" OFS "}";} {printf "%d fields : ",NF; for (i=1;i<=NF;i++) {printf "{" $i "} ";}; print "" }'
일부 줄을 여러 줄로 나누고, 다른 줄은 공백으로 시작합니다.)
sed 접근법 :
sed -i '/^[^C]*C[^C]*$/d' input
-i
옵션으로 전체 파일 수정 가능
/^[^C]*C[^C]*$/
- C
한 번만 포함 된 줄과 일치
d
-일치하는 줄 삭제
이것은 정확히 한 번의 C 발생으로 줄을 제거합니다.
grep -v '^[^C]*C[^C]*$' file
정규식 [^C]
은 C (또는 개행 문자)가 아닌 하나의 문자와 일치하며 반복 연산자 (일명 Kleene star) *
는 이전 식의 반복을 0 개 이상 지정합니다.
grep
(및 대부분의 다른 텍스트 지향 도구) 의 기본 출력은 표준 출력입니다. 새 파일로 리디렉션하고 원하는 경우 원본 파일 위로 이동하십시오. sed -i
내부 편집에 동일한 정규식을 사용할 수 있습니다 .
sed -i '/^[^C]*C[^C]*$/d' file
(일부 플랫폼, 특히 macOS를 포함한 * BSD의 경우 -i
옵션 에는와 같은 인수가 필요합니다 -i ''
.)
sed -i '/^[^C]*C[^C]*$/d' file
-이전에 게시 된 것처럼 들립니다. 표절은 어떻게 생각하십니까?
grep
대답으로 시작 했지만 분명히 sed -i
변형으로 쉽게 확장됩니다 . 이전 grep
답변 을 찾고 있었기 때문에 귀하의 답변을 보지 못했습니다 .
-i
에 sed
대신 새 파일로 리디렉션하고 경우에 그와 함께 원본을 대체 sed
유틸리티가 오류없이 종료.
grep -vx '[^C]*C[^C]*'
grep
더 명확하고 강력 하기 때문에 특히 유용 할 수 있습니다 (특히 sed
덜 유익한 종료 코드가 있음).
수정 된 내용을 표준 출력으로 인쇄하지 않고 파일의 스크립트 편집을위한 POSIX 도구는 ex
입니다.
printf '%s\n' 'g/^[^C]*C[^C]*$/d' x | ex file.txt
물론 Sed 버전이 지원 하는sed -i
경우 사용할 수 있습니다 . 다른 유형의 시스템에서 실행되는 스크립트를 작성하는 경우 이식성이 없다는 점에 유의하십시오.
David Foerster는 다음과 같이 논평했습니다.
왜 사용
printf
하고echo
있거나 아닌지에 대한 이유가ex -c COMMAND
있습니까?
답 : 예.
들어 printf
대 echo
그것은 이동성의 문제입니다; 에코보다 printf가 더 나은 이유를 참조하십시오 . 또한를 사용하여 명령 사이에 개행을 산재하는 것이 더 쉽습니다 printf
.
들어 printf ... | ex
대 ex -c ...
, 그것은 오류 처리의 문제입니다. 이 특정 명령의 경우 중요하지 않지만 일반적으로 중요합니다. 예를 들어
ex -c '%s/this pattern is not in the file/replacement text/g | x' filename
스크립트에서. 다음과 대조하십시오 :
printf '%s\n' '%s/no matching lines/replacement/g' x | ex file
첫 번째는 중단되고 입력을 기다립니다. 두 번째는 ex
명령 이 EOF를 수신하면 종료 되므로 스크립트가 계속됩니다. 와 같은 대체 해결 방법이 s///e
있지만 POSIX에서 지정하지 않았습니다. 위에 표시된 휴대용 양식을 사용하는 것이 좋습니다.
를 들어 g
명령이 있어야 끝에 줄 바꿈, 그리고 내가 사용하는 것을 선호 printf
명령을 포장하는 대신 작은 따옴표로 줄 바꿈을 삽입.
printf
하고 echo
있거나 아닌지에 대한 이유가 ex -c COMMAND
있습니까?
printf
vs. 에 대해 알았지 만 echo
(일반적으로 echo
인수가 하드 코딩 될 때 선호 하지만) ex
지금까지 광범위하게 사용하지는 않았습니다 .
다음은 perl을 사용하는 몇 가지 옵션입니다.
단일 문자 만 일치하므로 tr/C//
(대체없이 번역)을 사용 하여 다음과 일치하는 수를 반환 할 수 있습니다 C
.
perl -lne 'print if tr/C// != 1' file
보다 일반적으로 다중 문자 문자열 또는 정규식을 일치 시키려면 다음을 사용할 수 있습니다.
perl -lne 'print if (@m = /C/g) != 1' file
이것은 정규 표현식의 일치를 /C/g
리스트에 할당하고 리스트 @m
의 길이가 아닌 경우 행을 인쇄합니다 1
.
-i
스위치는 "현재 위치에서"편집에 추가 할 수 있습니다.
sed -e '
s/C/&/2;t # when 2nd C matches skip processing and print
/C/d # either one C or no C, so delete on C
'
sed -e '
/C/!b # no C, skip processing and print
/C.*C/!d # not(at least 2 C) => 1 C => delete
'
perl -lne 's/C/C/g == 1 or print'
sed
, t #...
일반적이라는 라벨로 분기 것이 #...
다른 대부분의 sed
구현.
b
, t
, :
, }
(그리고 r file
, w file
...) 같은 줄에 후 명령을 가질 수 없습니다. 별도의 -e
옵션을 사용할 수도 있습니다.
g
수정자를 추가하는 것을 잊었다 고 생각합니다 .
awk
구체적으로 원하는 사람 은
awk '/C[^C]*C/{next}//{print}'
패턴과 일치하면 줄을 건너 뛰고 그렇지 않으면 인쇄하십시오. 실제로 필요하지는 않습니다. 기본 인쇄를 {print}
사용할 수 //
있지만 철자가 더 명확하다고 생각합니다.
내 첫 번째 생각은 egrep -v
같은 패턴 으로 사용 하는 것이었지만 실제로 제기 된 질문에 대답하지는 않습니다.
{next}
? 그냥 말하면 awk '/pattern/ {next} 1'
패턴과 일치하지 않는 모든 줄이 인쇄됩니다. 또는 awk '!/pattern/'
직접 인쇄하는 것이 좋습니다 .
!/pattern/
(어쨌든 내 마음을 미끄러 뜨 렸지만 ) //{print}
은 cryptic보다 자기 설명 이 훨씬 낫습니다 1
. 코드를 유지 관리하기 위해 다음 사람의 능력과 유창함이 가장 낮다고 가정하십시오.
awk
필드 구분 기호 의 적절한 사용 !