간단한 file
포함의 경우:
1 a
2 b
3 c
4 d
5 e
6 f
7 g
8 h
9 i
10 j
나는 다음 명령을 사용합니다.
awk 'lines[NR]=$0 { print $lines[2]}'
그것은 나에게 다음을 제공합니다:
1 a
b
c
d
e
f
g
h
i
j
어떻게 그리고 왜? 이렇지 않아야합니까?
2 b
또한 다음을 업데이트하면
awk '{lines[NR]=$0} END { print lines[2]}' awk.write
2 b
그리고 사용$
j
답변1
awk
변수와 작업 흐름을 혼동하고 있습니다 . 아마도 원하는 것은 다음과 같습니다(두 번째 줄만 인쇄).
awk '{lines[NR]=$0} END{print lines[2]}' file
그러나 이는 다음과 같이 보다 간단하게 수행할 수 있습니다.
awk 'NR==2' file
질문에 다음을 수행하도록 명령합니다.
awk 'lines[NR]=$0 { print $lines[2]}'
lines[NR]=$0
awk
여기서는 조건으로 해석됩니다 .awk
다음과 같은 메커니즘을 갖춘 워크플로가 있습니다(모든 행에 적용됨 )'condition{instructions}'
.lines[NR]=$0
배열을 채우지만 이는 항상 true인 조건입니다. 이것이 바로{...}
명령 블록이 각 행에 대해 실행되는 이유입니다.print $lines[2]
배열의 두 번째 항목은 인쇄되지 않습니다lines[2]
.$lines[2]
이름이 배열의 두 번째 항목 내용인 변수로 확장됩니다. 첫 번째 줄은 초기화되지 않았으므로print
인수 없이 호출됩니다. 이는 전체 행을 인쇄한다는 의미입니다. 그러나 (다른 모든 줄에서) 설정하면 로 확장됩니다print $2
. 즉, 줄의 두 번째 필드가 인쇄됩니다.
답변2
에서는 awk
참조를 통해 변수 값에 액세스할 수 있습니다.
$ awk 'BEGIN {var=1; print var}'
1
가지다특수 변수필드 변수라고 하는 는 $
기호 뒤에 숫자나 표현식이 오는 방식으로 표시됩니다. 따라서 둘 다 첫 번째 필드의 값을 $1
제공합니다 .$(0+1)
lines
귀하의 예에서는 키가 행 번호이고 값이 전체 행인 연관 배열을 만들었습니다 . for 를 2
사용해야 하는 키 값을 얻으려면 n번째 필드를 참조해야 합니다 lines[2]
. $lines[2]
여기서 n번째는 의 반환 값입니다 lines[2]
.
첫 번째 행을 처리할 때 lines[2]
초기화되지 않아 반환될 수 있습니다.0또는비어 있는또는 다른 것(POSIX는 이 동작을 지정하지 않습니다). 어쨌든, print
과 는 print $0
동일합니다. 그래서 가 있는 이유는 첫 번째 행 1 a
입니다 .$0
두 번째 행부터 시작하여 lines[2]
두 번째 행의 내용으로 할당됩니다. 즉 2 b
, 숫자 컨텍스트에서 2 b
다음을 반환합니다 .2, 두 번째 행에서 두 번째 필드의 값을 가져오는 $2
식입니다.
이제 이후의 표현식은 $
POSIX에 지정된 숫자 결과를 반환한다고 보장되지 않으므로 다음과 같습니다.
필드 변수는 "$" 뒤에 숫자나 숫자 표현식이 와야 합니다. 이 맥락에서 음이 아닌 정수 이외의 것으로 평가되는 지정되지 않은 필드 숫자 표현식의 효과는 초기화되지 않은 변수 또는 문자열 값을 숫자 값으로 변환할 필요가 없습니다.
따라서 구현이 중단되는 상황이 있을 수 있습니다. 적어도Brian Kernighan 자신의 버전:
$ echo 1 2 | bawk '{print $b}'
bawk: illegal field $(), name "b"
input record number 1, file
source line number 1
0
어떤 경우든 다음을 추가하여 숫자 컨텍스트에서 표현식을 강제로 평가할 수 있습니다.
$ echo 1 2 | awk '{print $(b+0)}'
1 2