질문: "ㅏ"END 섹션에서 인쇄된 변수에는 모든 줄이 아닌 마지막으로 찾은 줄만 있습니다.
파일 1:
pattern .........
irrelevant text
irrelevant text
pattern .........
pattern .........
irrelevant text
이상한 코드:
awk '{ for (i=1; i<=NR; i++)
if ($i ~ /^pattern/) a+=$0
}
END {print $a}' file1
END 부분에서 패턴이 있는 행만 인쇄하고 싶습니다.
답변1
특정 패턴과 일치하는 모든 라인을 수집한 다음 마지막에 인쇄하려는 것 같습니다.
당신은 이것을 할 수 있습니다
awk '/^pattern/ { a[++n] = $0 }
END { for (i = 1; i <= n; ++i) print a[i] }' file
이는 a
배열 역할을 하며 패턴과 일치하는 각 행을 배열의 새 항목으로 추가합니다. 마지막으로 반복된 항목을 반복 a
하고 각 항목을 인쇄합니다.
pattern
전체 행에 대해 정규식을 일치시키는 대신 첫 번째 열에서 정확한 리터럴 문자열을 찾으려면 $1 == "pattern"
as 조건을 사용하세요.
하지만 만약 이것이모두하고 싶은 일을 하면 사용하기가 더 쉽습니다
awk '/^pattern/' file
pattern
또는 첫 번째 열의 리터럴 문자열 과 일치시키려는 경우
awk '$1 == "pattern"' file
그러면 패턴과 일치하는 각 행에 대한 기본 작업이 호출됩니다. pattern
두 번째 변형을 사용하는 경우 이를 첫 번째 열로 포함합니다. "기본 동작"은 행을 인쇄하는 것입니다.
에서는 현재 행의 값을 증가시키는 awk
산술 연산이 되며 a += $0
숫자로 해석됩니다. a
line을 문자열로 변수에 연결하려면 , 또는 추가된 문자열 앞에 개행 문자를 삽입하려는 경우 (기본값 )을 a
사용할 수 있습니다 . 하지만 나는 그 어떤 것도 여기서 하고 싶은 일이 아니라고 생각합니다.a = a $0
a = a ORS $0
ORS
답변2
코드에 몇 가지 문제가 있습니다.
일치하는 패턴을 테스트하기 위해 파일의 모든 행에 액세스하려고 하지만
{ ... }
이를 규칙 블록( ) 내에서 수행합니다. 하지만 모든 규칙이 처리됩니다.파일의 각 줄에 대해, 이러한 규칙에서는 현재 처리된 행의 내용에만 액세스할 수 있습니다. 암호{ for (i=1; i<=NR; i++) if ($i ~ /^pattern/) a+=$0 }
따라서 (조건이 앞에 오지 않기 때문에 파일의 모든 줄에 대해) 테스트를 시도합니다.필드1번부터
NR
- 어디야NR
?파일에서 현재 줄의 줄 번호, 현재 행의 필드 수 대신NF
추가해 보세요.현재 줄 전체a
이런 일이 발생할 때마다 변수를 가리킵니다. 패턴이 정규식에서 제안한 줄의 시작 부분에만 나타날 수 있다는 것이 사실이라면(앵커로 인해) 결과가 엉망이 될 수는 없지만^
적어도 극도로 비효율적입니다.현재 줄을 에 추가하려고 시도하는 동안
a
다음과 같이 씁니다.a+=$0
그러나 이는 줄(또는 최소한 공백으로 구분된 첫 번째 필드)이 숫자로 올바르게 해석될 수 있는 경우에만 잘 정의되며, 이 경우
a
/로 시작하는 모든 줄에만 표시됩니다. 파일에 나타나는 개별 번호. 행을 숫자로 해석할 수 없는 경우a
최종 값은 "0"입니다.END
블록 에서 선언한print $a
그러나 이것은 인쇄됩니다필드 번호
a
변수의 내용이 아닌 현재 줄의 내용입니다a
. 그러나 변수가a
"0"(포인트 2에서 언급한 대로)이므로 이는 전체 현재 행(일명$0
)을 참조합니다. 그리고 블록의 필드 번호에 대한 참조는END
항상 파일의 마지막 줄을 참조하므로(파일 끝에 "현재" 줄이 없기 때문에) 이 명령문은 필연적으로 파일의 마지막 줄 전체를 인쇄하고 다른 것은 없습니다.
특정 패턴과 일치하는 라인 인쇄에만 관심이 있는 것 같으므로 grep
이러한 유형의 작업 전용 도구를 사용하는 것이 더 쉬울 수 있습니다.
답변3
첫 번째 필드가 있는 모든 줄을 인쇄하려면 pattern
내용을 메모리에 저장하는 대신 찾은 모든 줄을 인쇄하면 됩니다.
awk '$1=="pattern"' file
심지어
grep -w '^pattern' file
반대로, 각 줄을 인쇄하려면어느이 행의 필드는 입니다 pattern
. 다음을 사용하세요.
awk '{ for(i=1; i<=NF; i++){ if($i=="pattern"){ print; next}}}' file
또는 필드 값만 찾고 있는 경우시작, pattern
그러나 그 뒤에 다른 문자가 있을 수 있습니다(코드에서 시도하는 문자). 첫 번째 필드만 원하는 경우 다음을 사용하세요.
awk '$1~/^pattern/' file
이는 모든 분야에 적용됩니다.
awk '{ for(i=1; i<=NF; i++){ if($i~/^pattern/){ print; next}}}' file
답변4
귀하의 질문을 올바르게 이해했다면 일치하는 모든 행을 연결하고 싶으 ^pattern
므로 이것이 귀하의 요구 사항을 충족할 것입니다.
echo $(grep '^pattern' infile)
awk
같은
echo $(awk '/^pattern/' infile)
아니면 awk
그냥 사용하세요:
awk '/^pattern/{ line = (line? line FS $0: $0) } END{ print line }' infile