나는 다음을 수행하려고 합니다(bash 사용). 항상 같은 이름을 가진 파일을 검색하고 해당 파일에서 데이터를 추출합니다. 추출된 데이터를 새 배열에 저장하고 싶은데 거의 다 온 것 같습니다. 아래 코드를 참조하세요.
내가 검색하고 있는 파일은 모두 다음과 같은 형식을 가지고 있습니다.
#!/bin/bash
echo "the concentration of NDPH is 2 mM, which corresponds to 2 molecules in a box of size 12 nm (12 x 12 x 12 nm^3)" > README_test
#find all the README* files and save the paths into an array called files
files=()
data1=()
data2=()
data3=()
while IFS= read -r -d $'\0'; do
files+=("$REPLY")
#open all the files and extract data from them
while read -r line
do
name="$line"
echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}'
echo "$name"
echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}'
data1+=( "$echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}' )" )
# variables are not preserved...
# data2+= echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /is/{f=1}'
echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /size/{f=1}'
# variables are not preserved...
# data3+= echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /size/{f=1}'
done < "$REPLY"
done < <(find . -name "README*" -print0)
echo ${data1[0]}
문제는 내가 원하는 파일의 정확한 출력을 제공하는 파이프가 루프 내에서 "작동하지 않는다"는 것입니다(변수를 보존하지 않음). 파이프 출력(data1, data2, data3)으로 채워진 배열을 얻기 위해 프로세스 대체를 사용할 수 있는지/방법을 모르겠습니다.
업데이트: 그래서 저는 배열에 물건을 올바르게 할당하지 않았습니다. (data1을 참조하세요. 지금은 올바르게 할당되고 있습니다.) 그런데 왜일까요?
echo ${data1[0]}
그리고
echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}'
아니 똑같아?
솔루션(ilkkachu의 답변을 기반으로 함):
#!/bin/bash
echo "the concentration of NDPH is 2 mM, which corresponds to 2 molecules in a box of size 12 nm (12 x 12 x 12 nm^3)" > README_test
files=()
data1=()
data2=()
data3=()
get_some_field() {
echo "$1" | tr ' ' '\n'| awk -vkey="$2" 'f{print;f=0;exit} $0 ~ key {f=1}'
}
#find all the README* files and save the paths into an array called files
while IFS= read -r -d $'\0'; do
files+=("$REPLY")
#open all the files and extract data from them
while read -r line
do
name="$line"
echo "$name"
echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}'
data1+=( "$(get_some_field "$name" of)" )
data2+=( "$(get_some_field "$name" is)" )
data3+=( "$(get_some_field "$name" size)" )
done < "$REPLY"
done < <(find . -name "README*" -print0)
echo ${data1[0]}
echo ${data2[0]}
echo ${data3[0]}
답변1
echo ... | awk
특히 배열 중 하나에 추가된 변수에 출력을 저장 하려고 한다고 가정합니다 .
먼저 명령의 출력을 캡처하려면 "$( cmd... )"
(명령 대체)를 사용합니다. 간단한 예로 호스트 이름이 인쇄됩니다.
var=$(uname -n)
echo $var
둘째, 배열에 추가하려면 오른쪽에 괄호가 있는 배열 할당 구문을 사용해야 합니다. 그러면 var
배열에 값이 추가됩니다 .
array+=( $var )
셋째, 확장 $var
및 명령 대체 는 $(...)
단어 분리기의 영향을 받으므로 단어 구분자를 괄호로 묶어야 합니다. 다시 간단한 예를 들자면 다음 uname -a
과 같은 완전한 출력이 제공됩니다 .하나의배열의 요소:
array+=( "$(uname -a)" )
또는 귀하의 경우에는 다음이 완료됩니다.
data1+=( "$(echo "$1" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}')" )
(명령 대체의 따옴표는 명령 대체의 따옴표와 동일하지 않습니다.외부그것. 이전 참조는 SE에서 강조 표시된 구문이 암시하는 것과는 달리 $1
external 에서 시작하는 참조를 중지하지 않습니다 . $()
)
파이프를 함수에 넣으면 더 쉽게 읽을 수 있습니다.
get_data1() {
echo "$name" | tr ' ' '\n'| awk 'f{print;f=0;exit} /of/{f=1}'
}
...
data1+=( "$(get_data1)" )
또는 파이프라인이 유사해 보이기 때문에 이 함수를 사용하여 코드 중복을 방지하세요.
get_some_field() {
echo "$1" | tr ' ' '\n'| awk -vkey="$2" 'f{print;f=0;exit} $0 ~ key {f=1}'
}
그런 다음
data1+=( "$(get_some_field "$name" of)" )
data2+=( "$(get_some_field "$name" is)" )
data3+=( "$(get_some_field "$name" size)" )
(파이프라인을 올바르게 읽었다면 위의 내용을 테스트하지 않은 것입니다.)