sed를 사용하여 4단어 한 줄 인쇄 [중복]

sed를 사용하여 4단어 한 줄 인쇄 [중복]

우분투 20.04에서 Bash를 사용하고 있습니다.

나는 파일을 가지고 있습니다 :

Hello hi 123
if a equals b
you
one abc two three four
dany uri four 123

sed단 4단어로 된 줄을 찾아야 합니다 . 이것은 제가 작성한 코드인데 작동하지 않고 파일을 정확하게 인쇄합니다.

sed "/[a-Z0-9+]{4}/g" F1

답변1

이 문제는 다음과 같이 필드를 쉽게 계산할 수 있는 도구로 해결되어야 합니다 awk.

$ awk 'NF == 4' file
if a equals b
dany uri four 123

이는 현재 레코드의 필드 수를 보유하는 NF특수 변수를 사용합니다. awk기본적으로 레코드는 한 줄이고 필드는 줄의 시작이나 끝 부분에 있는 빈 필드를 제외하고 하나 이상의 공백 문자(탭 또는 공백)로 구분된 하위 문자열입니다. 위의 짧은 프로그램은 awk정확히 4개의 필드를 포함하는 모든 라인을 출력합니다.


를 사용하는 경우 sed공백으로 구분된 하위 문자열을 일치시켜야 합니다.

sed기본 정규식은 기본적으로 사용되며 표시되는 표현식은 확장 정규식 수정자인 을 사용 합니다 {4}. 기본 정규식에 해당하는 내용이 작성됩니다 \{4\}. 또한 유효하지 않은 문자 범위를 사용하고 a-Z있으며 사용하려는 문자 클래스는 로 작성하는 것이 더 좋습니다 [[:alnum:]]. 즉, 모든 영숫자 문자와 일치하는 것입니다(include가 +철자가 틀린 것으로 가정). "예약된 공간"에서 데이터를 가져오기 위한 후행 g명령이 잘못된 것 같습니다.

여기서 나의 일반적인 아이디어는 각 단어(공백이 아닌 문자 하나 이상)를 단일 x단어로 압축한 다음 모든 공백 문자(탭 또는 공백)를 제거하는 것입니다. 결과 문자열이 이면 xxxx원래 줄을 인쇄합니다(그렇지 않으면 줄을 삭제하고 즉시 다음 루프를 시작합니다).

sed -e h \
    -e 's/[^[:blank:]]\{1,\}/x/g' \
    -e 's/[^x]//g' \
    -e '/^xxxx$/!d' \
    -e g file

여기서 원래 줄은 먼저 를 사용하여 "예약된 공간"에 저장한 h다음 인쇄해야 할 경우 다시 꺼내어 g마지막으로 사용합니다. 두 번째부터 마지막 ​​줄 까지 d의 명령이 실행되면 g마지막 줄은 고려되지 않습니다.

또는 확장 정규식을 사용하세요.

sed -E -e h \
    -e 's/[^[:blank:]]+/x/g' \
    -e 's/[^x]//g' \
    -e '/^xxxx$/!d' \
    -e g file

시험:

$ sed -e h \
>     -e 's/[^[:blank:]]\{1,\}/x/g' \
>     -e 's/[^x]//g' \
>     -e '/^xxxx$/!d' \
>     -e g file
if a equals b
dany uri four 123

[[:alnum:]](공백이 아닌) 대신 클래스로 단어 문자를 정의하려면 [^[:blank:]]위 표현식을 [^[:blank:]]로 변경하세요. [[:alnum:]]차이점은 GNU/Linuxor 와 같은 문자열은 Unix-system각 단어가 아닌 두 단어로 처리된다는 것입니다.

답변2

GNU 사용 sed:

$ sed -E '/^\s*(\w+\s+){3}\w+\s*$/!d' infile
if a equals b
dany uri four 123

POSIXly 다음과 같이 작성할 수 있습니다.

sed '/^[[:space:]]*\([_[:alnum:]][_[:alnum:]]*[[:space:]][[:space:]]*\)\{3\}[_[:alnum:]][_[:alnum:]]*[[:space:]]*$/!d' infile

답변3

우리가 만든 정규식을 활용 하여 GNU sed선택적 선행 공백을 찾은 다음 정확히 4쌍의 비공백 + 공백, 패턴 공간의 끝을 찾습니다.

$ sed -nE 'G;/^\s*(\S+\s+){4}$/P' F1

또는,

sed -nE '
  s/\S+/&/4;T    # 3 or less chunks
  s//&/5;t       # 5 or more chunks 
  p              # exactly 4 chunks 
' F1

sed -E '
  s/\S+/&/5; td     # 5 or more chunks
  s//&/4; t         #  exactly 4 chunks
  :d;d              # 3 or less or 5 or more
' F1

답변4

분명히 awk이 사용 사례에 대한 더 나은 도구이지만 이것이 OP가 지정한 것입니다 sed.

GNU를 사용하면 sed다양한 솔루션이 가능합니다 . 예약된 공간을 사용하는 것은 다음과 같습니다.

$ cat -A file
Hello hi 123$
if a equals b$
you$
one abc two three four$
dany uri four 123$
   one two three four$
    five  six ^Iseven eight      $

$ sed -e 'h; s/^\s*//; s/\s*$//' -nre '/^\w+(\W+\w+){3}$/{g;p}' file
if a equals b
dany uri four 123
   one two three four
    five  six   seven eight      
$

명령은 sed다음과 같이 단순화될 수 있습니다.

$ sed -nr '/^\s*(\w+)(\W+\w+){3}\s*$/p' file

대신 POSIX 문자 클래스를 사용하는 이전 명령 sed의 이식성이 더 높은 또 다른 버전 은 다음과 같습니다 .-E-r

$ sed -En '/^[[:blank:]]*[[:alnum:]]+([[:blank:]]+[[:alnum:]]+){3}[[:blank:]]*$/p' file

관련 정보