awk 반복 {n}이 작동하지 않습니다


18

반복 기호 {n}을 사용하여 줄을 인쇄하려고하는데 작동하지 않습니다. 에 대한. 예를 들어 길이가 4 자 길이 인 모든 줄을 인쇄하고 싶습니다.

 awk '/^.{4}$/' test_data

위의 코드는 인쇄하지 않습니다. 반복 기호를 사용할 수 있도록 수정하는 방법은 무엇입니까? 내가 좋아하는 대안을 알고 awk '/^....$/' test_dataawk 'length ==3 ' test_data


3
어떤 배포판을 사용하고 있습니까? 어느 awk?
terdon

1
$ awk --version GNU Awk 3.1.7 $ cat / etc / redhat-release Red Hat Enterprise Linux 서버 릴리즈 6.7 (Santiago)
Forever Learner

2
나는 awk '/^.{4}+$/{print}' <<<$'foods\nbaarsz\nfooo' 정확히 4 문자에 일치 한다고 말하고 싶습니다 . 또한 자신을 언급했듯이 awk 'length($0) == 4' test_data거의 모든 awk버전 과 호환 됩니다.
Valentin Bajrami 2016 년

4
합니까 awk --re-interval '/^.{4}$/' test_data 아니면 awk --posix '/^.{4}$/' test_data작동합니까?
steeldriver

스틸 드라이버 감사합니다. 이것은 내 문제를 해결했습니다. 공감. 다시 한번 감사드립니다 :)
Forever Learner

답변:


19

GNU Awk 사용자 안내서 : 기능 히스토리 에 따르면 정규 표현식 범위 연산자에 대한 지원이 버전 3.0에서 추가되었지만 처음에는 명시 적 명령 행 옵션이 필요했습니다.

새로운 명령 줄 옵션 :

  • 새로운 명령 줄 옵션 :
    • --lint-old 옵션은 원래 버전 7 Unix 버전 awk에서 사용할 수없는 구문에 대해 경고합니다 (V7 / SVR3.1 참조).
    • BWK awk의 -m 옵션. (브라이언은 당시 여전히 벨 연구소에있었습니다.) 이것은 나중에 그의 awk와 gawk에서 제거되었습니다.
    • --re-interval 옵션은 regexp에서 간격 표현식을 제공합니다 (Regexp 연산자 참조).
    • --traditional 옵션이 --compat의 더 나은 이름으로 추가되었습니다 (옵션 참조).

에서 gawk4.0,

간격 표현식은 기본 정규 표현식의 일부가되었습니다

당신이 사용하고 있기 때문에 gawk3.X를, 당신은 사용해야합니다

awk --re-interval '/^.{4}$/'

또는

awk --posix '/^.{4}$/'

또는 (@ StéphaneChazelas 덕분에) 휴대용 솔루션을 원한다면

POSIXLY_CORRECT=anything awk '/^.{4}$/'

(이후 --posix또는 --re-interval다른 오류 원인이 awk구현).


시간과 도움을 주셔서 감사합니다. 답변으로 찬성 및 수락
Forever Learner

4
POSIXLY_CORRECT=anything awk '/^.{4}/'이식 가능한 코드를 만드는 것처럼 사용 하는 것이 좋습니다 ( --posix또는 --re-interval다른 awk구현 에서는 오류가 발생할 수 있습니다 ).
Stéphane Chazelas

안녕 Stéphane Chazelas, $ POSIXLY_CORRECT = anything awk '/^.{4}/'test_data 명령을 실행하면 모든 행이 인쇄됩니다. 그런 다음 반복 후 마지막 달러가 없다는 것을 깨달았습니다. 입력 해 주셔서 감사합니다. 귀하의 의견과 해결책을지지합니다. 죄송합니다. 반복 후 $를 생략하여 처음부터 오해했습니다.
Forever Learner

20

ERE ( 또는에 의해 사용되는 확장 정규식 )에는 처음에.가 없었습니다 . BRE ( 또는에 의해 사용됨)에서 처음 소개 되었지만 이전 버전의 이식성을 깨뜨리지 않는 구문으로 제공되었습니다.awkegrep{x,y}grepsed\{x,y\}

그러나 해당 {x,y}구문 으로 ERE에 추가되었을 때 foo{2}RE가 이전과 다른 것과 일치 했기 때문에 이식성이 떨어졌습니다 .

따라서 일부 구현은 그렇게하지 않기로 선택했습니다. 당신은 그것을 찾을 수 있습니다 /bin/awk, /bin/nawk/bin/egrepSolaris에서 여전히 (당신이 사용할 필요를 존중하지 않는다 /usr/xpg4/bin/awk거나 /usr/xpg4/bin/grep -E). 에 대한 동일 awknawkFreeBSD의에 (에 따라 브라이언 커니 핸으로 유지 합니다 ( 에서 )).awkkawk

GNU의awk 경우 비교적 최근 (버전 4.0) POSIXLY_CORRECT=anything awk '/^.{4}$/'까지는이를 존중하기 위해이를 호출해야 했습니다. mawk여전히 그것을 존중하지 않습니다 .

연산자는 구문 설탕 일뿐입니다. 예를 들어 .{3,5}항상 쓸 수 있습니다 ....?.?(물론 {3,5}훨씬 더 읽기 쉽고 그에 상응하는 (foo.{5,9}bar){123,456}것이 훨씬 나쁩니다).


Stéphane Chazelas에게 다시 한번 감사드립니다. 죄송합니다, 처음에는 귀하의 답변을 이해할 수 없었습니다. 많은 감사와 공감.
Forever Learner

6

이것은 GNU awk(gawk)에서 예상대로 작동합니다 .

$ printf 'abcd\nabc\nabcde\n' | gawk '/^.{4}$/'
abcd

그러나 실패 mawk POSIX에 더 가까운 는 awkUbuntu 시스템의 기본값 인 AFAIK입니다.

$ printf 'abcd\nabc\nabcde\n' | mawk '/^.{4}$/'
$ ## prints nothing

따라서 간단한 해결책은 gawk대신에 사용하는 것입니다 awk. {n}표기는 POSIX BRE (기본 정규식) 구문의 일부가 아니다. 그 이유입니다grep 여기에서도 실패합니다.

$ printf 'abcd\nabc\nabcde\n' | grep '^.{4}$'
$

그러나 ERE (확장 정규식)의 일부입니다.

$ printf 'abcd\nabc\nabcde\n' | grep -E '^.{4}$'
abcd

mawkPOSIX awk에서 어떤 정규식 풍미가 사용되는지 모르겠지만 BRE라고 생각합니다.. 그들은 Stéphane의 답변 에 따라 이전 버전의 ERE를 사용합니다 . 어쨌든 awkERE를 구현하지 않는 버전을 사용하고 있거나 입력에 실제로 정확히 4자를 가진 행이없는 경우가 있습니다. 예를 들어, 공백이 없거나 글리프를 유니 코드로 인해 발생할 수 있습니다.


안녕하세요 terdon, 나는 4 자 길이의 줄을 인쇄하고 싶습니다. 줄의 처음 네 문자가 아닙니다. 예를 들어 $ grep -E '^. {4} $'test_data는 작동하지만 awk와 작동하지 않습니다
Forever Learner

@CppLearner 예, 제가 여기서하고있는 일입니다. 무슨 소리 야?
terdon

@terdon의 솔루션 @CppLearner는 길이가 4자인 행만 인쇄합니다. 그러나 실제로 줄 길이에만 관심이 있다면 정규 length($0)표현식보다 효율적인 것을 사용해야 합니다.
Stephen Kitt

안녕하세요 terter, steeldriver의 솔루션은 내가 찾고있는 것입니다. 시간 내 줘서 고마워. 안녕하세요 Stephen Kitt, 문제에서 언급했듯이 이미 길이를 대안으로 사용했기 때문에 반복 정규 표현식 {n}이 스틸 드라이버의 의견에서 작동하지 않는 이유에 대해 더 관심이있었습니다. --re-interval 또는 --posix. 시간 내 줘서 고마워.
Forever Learner

1
mawk실제로 POSIX awk에 가깝지 않으며 BRE를 사용하지 않습니다. ERE를 사용하지만 {x,y}운영자 는 사용하지 않습니다 .
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.