awk에서 찾은 각 항목을 배열에 저장
내 이전 질문은 "중복"으로 표시되었고 나는 이것 과 이것 에 대해 지적 했습니다 . 해당 스레드에서 제공되는 솔루션은이 문제를 전혀 해결하지 못합니다.
file.txt의 내용 :
Some line of text 0
Some line of text 1
Some line of text 2
PATTERN1
Some line of text 3
Some line of text 4
Some line of text 5
PATTERN2
Some line of text 6
Some line of text 7
Some line of text 8
PATTERN1
Some line of text 9
Some line of text 10
Some line of text 11
PATTERN2
Some line of text 12
Some line of text 13
Some line of text 14
사이에 "PATTERN1"과 "PATTERN2"+ 줄을 추출해야합니다. 다음 명령은이 작업을 완벽하게 수행합니다.
awk '/ PATTERN1 /, / PATTERN2 /'./file.txt
산출:
PATTERN1 Some line of text 3 Some line of text 4 Some line of text 5 PATTERN2 PATTERN1 Some line of text 9 Some line of text 10 Some line of text 11 PATTERN2
하지만 이제 다음과 같은 bash 스크립트를 만들려고합니다.
- awk를 사용하여 PATTERN1과 PATTERN2 사이의 줄을 찾습니다.
- 배열에 PATTERN1 + 줄 사이의 각 발생 + PATTERN2 저장
- 파일 끝까지 1 & 2를 수행합니다.
명확히하기 위해. 따옴표 안에 다음 줄을 저장하는 것을 의미합니다.
"PATTERN1
Some line of text 3
Some line of text 4
Some line of text 5
PATTERN2"
...에 array[0]
따옴표 안에 다음 줄을 저장하십시오.
"PATTERN1
Some line of text 9
Some line of text 10
Some line of text 11
PATTERN2"
...에 array[1]
등등 ..... PATTERN1 및 PATTERN2가 더 많이 발생하는 경우
내가 현재 가지고있는 것 :
#!/bin/bash
var0=`cat ./file.txt`
mapfile -t thearray < <(echo "$var0" | awk '/PATTERN1 /,/PATTERN2/')
위는 작동하지 않습니다.
스크립트가 지원하지 않는 시스템에서 실행될 수 있으므로 가능한 한 맵 파일을 사용하고 싶지 않습니다.
제공된 이 링크를 기반으로 :
myvar=$(cat ./file.txt)
myarray=($(echo "$var0" | awk '/PATTERN1 /,/PATTERN2/'))
하지만 내가 할 때 echo ${myarray[1]}
빈 응답을받습니다.
그리고 내가 할 때 echo ${myarray[0]}
나는 얻다:
PATTERN1 Some line of text 3 Some line of text 4 Some line of text 5 PATTERN2 PATTERN1 Some line of text 9 Some line of text 10 Some line of text 11 PATTERN2
에코 할 때 기대하는 것 ${myarray[0]}
PATTERN1 Some line of text 3 Some line of text 4 Some line of text 5 PATTERN2
내가 할 때 기대하는 것 echo ${myarray[1]}
PATTERN1 Some line of text 9 Some line of text 10 Some line of text 11 PATTERN2
어떤 도움이라도 좋을 것입니다.
답변
로 찰스 제안 ...
블록 에서 줄 바꿈을 제거하도록 편집 됨 (모든 레코드가 아님)
while IFS= read -r -d '' x; do array+=("$x"); done < <(awk ' /PATTERN1/,/PATTERN2/ { if ( $0 ~ "PATTERN2" ) { x=$0; printf "%s%c",x,0; next }
print }' ./file.txt)
다시 포맷했습니다. 조금 바쁘고 읽기가 어려워졌습니다.
그리고 그것을 테스트하기 위해-
$: echo "[${array[1]}]"
[PATTERN1
Some line of text 9
Some line of text 10
Some line of text 11
PATTERN2]
제쳐두고, 데이터 요소에 중복 된 센티넬 값을 포함하는 것은 매우 이상해 보입니다.
$: while IFS= read -r -d '' x; do array+=("$x"); done < <( awk '/PATTERN1/,/PATTERN2/{ if ( $0 ~ "PATTERN1" ) { next }
if ( $0 ~ "PATTERN2" ) { len--; for (l in ary) { printf "%s%c", ary[l], l<len ? "\n" : 0; } delete ary; len=0; next } ary[len++]=$0;
}' ./file.txt )
$: echo "[${array[1]}]"
[Some line of text 9
Some line of text 10
Some line of text 11]
일반 구현은 bash
다음과 같을 수 있습니다.
#!/bin/bash
beginpat='PATTERN1'
endpat='PATTERN2'
array=()
n=-1
inpatterns=
while read -r; do
if [[ ! $inpatterns && $REPLY = $beginpat ]]; then array[++n]=$REPLY
inpatterns=1
elif [[ $inpatterns ]]; then array[n]+=$'\n'$REPLY if [[ $REPLY = $endpat ]]; then inpatterns= fi fi done # Report captured lines for ((i = 0; i <= n; ++i)); do printf "=== array[%d] ===\n%s\n\n" $i "${array[i]}"
done
로 실행 ./script < file
. 의 사용은 awk
필수는 아니지만 스크립트는 awk
출력에서도 올바르게 작동합니다 .
Paul의 대답은 내가 원하는 것을 수행하므로 수락 된 대답으로 표시했습니다. 그의 솔루션은 배열의 모든 저장된 값의 맨 아래에 빈 추가 라인을 생성하지만 괜찮습니다. 어쨌든 제거하기가 쉽기 때문에 신경 쓰지 않았습니다. 그러나 나는 또한이 같은 질문을 다른 사이트에 게시했으며 Paul의 대답은 좋았지 만 더 나은 해결책을 찾았습니다.
IFS=$'\r' read -d'\r' -a ARR < <(awk '/PATTERN1/,/PATTERN2/ {if($0 ~ /PATTERN2/) printf $0"\r"; else print}' file.txt)
위의 내용은 작업을 수행하고 빈 추가 줄을 생성하지 않으며 하나의 라이너입니다.
echo "${ARR[1]}"
echo "${ARR[0]}"
산출:
PATTERN1
Some line of text 9
Some line of text 10
Some line of text 11
PATTERN2
PATTERN1
Some line of text 3
Some line of text 4
Some line of text 5
PATTERN2