awk 'NR%2 == 1?ORS=";":ORS="\n"'에서 구문 오류가 발생하는 이유는 무엇입니까?

awk 'NR%2 == 1?ORS=";":ORS="\n"'에서 구문 오류가 발생하는 이유는 무엇입니까?

나는 Hackerrank 문제를 해결하고 있으며 결과는 다음과 같습니다.

A 25 27 50;B 35 37 75
C 75 78 80;D 99 88 76 

입력용

A 25 27 50
B 35 37 75
C 75 78 80
D 99 88 76.

ORS위의 작업을 수행하는 데 사용하고 있습니다 . 그런데 왜 런타임 오류가 발생하는지 모르겠습니다.

awk 'NR%2 == 1?ORS=";":ORS="\n"'

발생하는 오류는

awkNR: cmd. line:1: Possible syntax error

답변1

괄호로 묶이지 않은 삼항 표현식은 이미 언급된 컨텍스트 및 awk 버전뿐만 아니라 다양한 컨텍스트의 다양한 awk 버전에서 구문 오류를 발생시킵니다. MacOS의 또 다른 예는 다음과 같습니다.

$ awk --version
awk version 20070501

$ awk 'BEGIN{print 1 == 2 ? 3 : 4}'
awk: syntax error at source line 1
 context is
    {print 1 >>>  == <<<
awk: illegal statement at source line 1
awk: illegal statement at source line 1

$ awk 'BEGIN{print (1 == 2 ? 3 : 4)}'
4

$ awk 'BEGIN{print (1 == 2) ? 3 : 4}'
4

작동하는 두 가지 방법 중 print (1 == 2 ? 3 : 4)특히 중첩된 트리플을 얻을 때 더 읽기 쉬운 방법을 찾았습니다.

$ awk 'BEGIN{print (1 == 2 ? (6 == 7 ? 8 : 3) : 4)}'
4

$ awk 'BEGIN{print (1 == 2) ? (6 == 7) ? 8 : 3 : 4}'
4

그래서 이것이 제가 일반적으로 사용하는 것이며 일반적으로 가독성을 위해 유용한 조건 주위에 괄호를 추가합니다.

괄호로 묶인 트리플은 항상 괄호가 없는 트리플보다 읽기 쉽기 때문에 괄호가 없는 트리플을 작성할 이유가 전혀 없습니다.

또한 조건부 컨텍스트에서 할당을 사용해서는 안 됩니다.필요과제의 결과는 조건으로 평가되지만 반드시 그럴 필요는 없습니다.

당신이하고 싶은 일은 다음과 같이 작성되어야합니다 :

$ awk '{ORS=(NR%2 ? ";" : RS)} 1' file
A 25 27 50;B 35 37 75
C 75 78 80;D 99 88 76

답변2

Busybox에서는 awk마지막 두 피연산자 주위에 괄호가 필요한 것 같습니다.

같은 오류가 발생합니다.

$ busybox awk 'NR%2 == 1?ORS=";":ORS="\n"' file
awkNR: cmd. line:1: Possible syntax error

하지만 그것은 작동합니다

$ busybox awk 'NR%2 == 1?(ORS=";"):(ORS="\n")' file
A 25 27 50;B 35 37 75
C 75 78 80;D 99 88 76

답변3

어색한 인용 문자열을 피하기 위해 다시 작성하면 구성은 다음과 같습니다.

1 > 0 ? a = 1 : a = 2

와 같을 수 있기 때문에 완전히 모호하지는 않습니다 (1 > 0) ? (a = 1) : (a = 2). 그러나 POSIX에 따르면,할당은 조건부 연산자보다 우선순위가 낮습니다. ?:, 따라서 Busybox는 아마도 그런 식으로 구문 분석을 시도할 것이지만 (1 > 0 ? a) = (1 : a) = (2)실제로는 작동하지 않습니다.

C에서도 작동하지 않습니다(Debian의 경우 gcc 6.3.0-18+deb9u1). 따라서 여기에서 Busybox가 완전히 잘못되었다고 말할 수는 없습니다.

/tmp$ cat ternary.c
int main(void)
{
    int a;
    1 > 0 ? a = 11 : a = 22;
}
/tmp$ gcc -Wall -o ternary ternary.c 
ternary.c: In function ‘main’:
ternary.c:4:24: error: lvalue required as left operand of assignment
     1 > 0 ? a = 11 : a = 22;
                        ^

(내 생각에는 stackoverflow의 언어 변호사가 우리가 이것을 해야 하거나 하지 말아야 하는 이유와 방법을 정확하게 말해 줄 수 있다고 생각합니다.)

과제 주위에 괄호를 추가할 수 있지만~해야 한다로 작성됩니다 a = 1 > 0 ? 11 : 22. 이것이 할당의 우선 순위가 낮은 이유입니다 . 그렇지 않은 경우 일반적으로 원하는 것이 무엇인지 ?:결정됩니다 .(a = (1 > 0)) ? 11 : 22

반면, 할당된 대상을 조건에 따라 변경하려면 다음을 수행하세요.정말로 그래야 한다명확성을 위해 if대신 완전한 문장을 사용하세요 1 > 0 ? (a = 11) : (b = 22).

답변4

아마도:

echo "${cccccccc}"
echo
echo "${cccccccc}" \
\
| mawk -F. 'ORS=substr(";\n",_-(NR%_--),NF=_++)' \_=2 OFS= | ecp

A 25 27 50
B 35 37 75
C 75 78 80
D 99 88 76.

 
A 25 27 50;B 35 37 75
C 75 78 80;D 99 88 76

훨씬 더 간단합니다. 많은 내장 변수를 사용하여 무거운 작업을 수행하는 솔루션입니다.

mawk -F. 'NF=sub(FS,(NR % _)?":" :"\n",ORS)' OFS='' \_=2

특정 getline접근 방식을 선호하는 경우 이를 파악하기 위해 노력할 필요조차 없습니다 NR % 2.

 echo;  echo "${cccccccc}"
 echo;  echo "${cccccccc}" \
 \
 | mawk -F. '$!_=$-_=sprintf("%s;%s",$( NF ^= !NF ),
                                     $!(NF  = getline))' OFS=''

A 25 27 50
B 35 37 75
C 75 78 80
D 99 88 76.

 
A 25 27 50;B 35 37 75
C 75 78 80;D 99 88 76

멋진 구문을 정말 좋아한다면 가능합니다.

mawk -F. 'sub("^",($!(NF = !_))";",$!(NF = getline))' OFS=


A 25 27 50
B 35 37 75
C 75 78 80
D 99 88 76.

 
A 25 27 50;B 35 37 75
C 75 78 80;D 99 88 76

관련 정보