참고: Jeff Schaller와 Steeldriver에게 감사드립니다. 그러나 둘 다 답변으로 게시되지 않았으므로 해결된 것으로 표시하는 방법을 잘 모르겠습니다. 이제 파이프/서브쉘에 대해 더 잘 이해하게 되었습니다. 나는 이것을 한 번 알았을 것이라고 확신하지만 bash에서 복잡한 것을 시도한 것은 오랜 시간이 걸렸습니다.
둘 다 awk의 필터링된 결과를 변수에 할당하고프로세스 교체나를 위해 작동합니다. 정렬되지 않은 고유 행을 읽는 최종 코드는 다음과 같습니다 stdin
.
while read -r FILE
do
...
done < <(awk '!x[$0]++')
더 읽어보기프로세스 교체이 질문을 발견하고 유사한 문제에 대한 해결책을 찾고 있는 사람들을 위한 것입니다.
원래 질문:
사이트를 검색했지만 내 질문에 대한 답변을 찾을 수 없습니다.
표준 입력에서 배열을 작성 중이며 고유한 행을 필터링해야 합니다. 이를 위해 나는 awk '!x[$0]++'
내가 읽은 약어를 사용하고 있습니다.
awk 'BEGIN { while (getline s) { if (!seen[s]) print s; seen[s]=1 } }'
.
필터는 예상대로 작동하지만 문제는 루프에서 생성된 배열이 while read
비어 있다는 것입니다.
$list
예를 들어( 의 대안으로 사용됨 stdin
):
list=$'red apple\nyellow banana\npurple grape\norange orange\nyellow banana'
while read -r line; do
array[count++]=$line
done <<< "$list"
echo "array length = ${#array[@]}"
counter=0
while [ $counter -lt ${#array[@]} ]; do
echo ${array[counter++]}
done
생산하다:
array length = 5
red apple
yellow banana
purple grape
orange orange
yellow banana
그러나 $list
awk로 필터링합니다.
list=$'red apple\nyellow banana\npurple grape\norange orange\nyellow banana'
awk '!x[$0]++' <<< "$list" | while read -r line; do
array[count++]=$line
done
echo "array length = ${#array[@]}"
counter=0
while [ $counter -lt ${#array[@]} ]; do
echo ${array[counter++]}
done
생산하다:
array length = 0
그러나 출력은 awk '!x[$0]++' <<< "$list"
괜찮아 보입니다.
red apple
yellow banana
purple grape
orange orange
while read
루프의 각 줄을 확인해 보았습니다 .
list=$'red apple\nyellow banana\npurple grape\norange orange\nyellow banana'
i=0
awk '!x[$0]++' <<< "$list" | while read -r line; do
echo "line[$i] = $line"
let i=i+1
done
좋아 보인다:
line[0] = red apple
line[1] = yellow banana
line[2] = purple grape
line[3] = orange orange
내가 여기서 무엇을 놓치고 있는 걸까요?
중요한 경우 bash 3.2.57을 사용하고 있습니다.
GNU bash, 버전 3.2.57(1)-릴리스(x86_64-apple-darwin15) Copyright (C) 2007 Free Software Foundation, Inc.
답변1
awk '!x[$0]++' <<< "$list" |또한 -r 행을 읽으십시오. 대량으로[개수++]=$행 완벽한
이것array
(이탤릭체) 이 경우에는 다음의 일부입니다.subshell
(용감한).
그리고 가치가 $line
있습니다$array
동시에Zi Ke가 살아 있다고 말할 수 있습니다.
서브셸이 완료되면(즉, 종료되면) 상위(생성기) 환경이 복원됩니다. 여기에는 서브셸에 설정된 모든 변수 제거가 포함됩니다.
이 경우:
삭제,$array
삭제되었습니다.$line
이 시도:
list=$'red apple\nyellow banana\npurple grape\norange orange\nyellow banana'
awk '!x[$0]++' <<< "$list" | while read -r line; do
array[count++]=$line
printf "array[%d] { %s\n" ${#array[@]} # array[num_of_elements] {
printf " %s\n" "${array[@]}" # elements
printf "}\n" # } end of array
done
printf "\n[ %s ]\n\n" "END OF SUBSHELL (PIPE)"
printf "array[%d] {\n" ${#array[@]}
printf " %s\n" "${array[@]}"
printf "}\n"
생산하다:
array[1] {
red apple
}
array[2] {
red apple
yellow banana
}
array[3] {
red apple
yellow banana
purple grape
}
array[4] {
red apple
yellow banana
purple grape
orange orange
}
[ END OF SUBSHELL (PIPE) ]
array[0] {
}
아니면 매뉴얼을 따르세요.
우리는부터 시작할 수 있습니다관로
[...] 파이프라인의 각 명령은 자체적으로 실행됩니다.서브쉘(바라보다명령 실행 환경). […]
게다가명령 실행 환경모험은 다음과 같이 확장됩니다.
[...] 여기서 호출되는 명령은독립적인 환경 할 수 없다쉘의 실행 환경에 영향을 줍니다.
명령 대체, 괄호로 묶인 명령 및 비동기 명령은 쉘 환경과 중복되는 서브 쉘 환경에서 호출됩니다. 단, 쉘에 의해 잡힌 트랩은 쉘이 상위 쉘에서 상속받은 값으로 재설정됩니다. 기도. 파이프라인의 일부로 호출되는 내장 명령은 서브셸 환경에서도 실행됩니다.서브쉘 환경에 대한 변경은 쉘의 실행 환경에 영향을 주지 않습니다.[…]
영향을 미치지 않으므로 설정할 수 없습니다.
그러나 다음 방향으로 리디렉션하고 작업을 수행할 수 있습니다.
list=$'red apple\nyellow banana\npurple grape\norange orange\nyellow banana'
while read -r line; do
arr[count++]=$line
done <<<"$(awk '!x[$0]++' <<< "$list")"
echo "arr length = ${#arr[@]}"
count=0
while [[ $count -lt ${#arr[@]} ]]; do
echo ${arr[count++]}
done
답변2
문제에 대한 몇 가지 해결책루프 없음
# use bash's mapfile with process substitution
mapfile -t arr < <( awk '!x[$0]++' <<<"$list" )
# use array assignment syntax (at least bash, ksh, zsh)
# of a command-substituted value split at newline only
# and (if the data can contain globs) globbing disabled
set -f; IFS='\n' arr=( $( awk '!x[$0]++' <<<"$list" ) ); set +f