내가 아는 한 awk는 두 가지 방법으로 사용될 수 있습니다. 파일 목록을 매개변수로 전달하거나 파이프라인에서 사용할 수 있습니다. 파일 목록을 매개변수로 사용해 보았으므로 BEGIN
and END
블록은 모든 파일에 대해 한 번만 실행됩니다. 하지만 문제가 있습니다. 파일을 awk에 전달하려면 먼저 파일의 암호를 해독해야 합니다. 그래서 다음과 같이 파이프라인을 설정했습니다.
find . -name "*.gpg" -exec sh -c "gpg -d {} | awk -f process.awk" \;
이제 모든 파일이 실행 BEGIN
되고 END
차단되는데 process.awk
이는 내가 원하는 것이 아닙니다. 블록이 한 번만 실행되도록 awk에 전달된 파일을 해독하는 방법이 있습니까? 업데이트: 파일 이름도 필요하기 때문에 process.awk
파일 내용을 별도로 가져오는 것이 더 좋을 것이라고 생각했습니다. 하지만 그러면 찾은 모든 파일에 대해 한 번만 수행해야 한다는 요구 사항을 위반하게 됩니다. 맞습니까 BEGIN
?END
답변1
파일 이름에 개행 문자가 포함되어 있지 않다고 가정합니다.
while IFS= read -r fname; do
gpg -d "$fname"
done < <(find . -name '*.gpg') |
awk -f process.awk
지금 말하는 작업을 수행하고 각 파일 이름을 awk에 전달하려면 가장 간단한 방법은 다음과 같습니다(bash 4.*를 사용 readarray
하거나 mapfile
채우는 루프를 작성한다고 가정 fnames[]
).
readarray -t fnames < <(find . -name '*.gpg')
for fname in "${fnames[@]}"; do
gpg -d "$fname" |
awk -v fname="$fname" -v tot="${#fnames[@]}" -v nr="$((++nr))" -f process.awk
done
이렇게 하면 각 파일 이름이 있고 fname
코드가 및 섹션에서 실행되는지 테스트할 수 있습니다.nr==1
BEGIN
nr==tot
END
BEGIN {
if (nr==1) {
do BEGIN stuff
}
}
{ do common stuff }
END {
if (nr==tot) {
do END stuff
}
}
또는 임시 파일을 위한 공간이 있는 경우 호출을 반복 gpg
하고 모든 출력을 동일한 이름의 파일에 대한 임시 디렉터리에 쓴 다음 변경하지 않고도 각 파일에 대해 awk를 호출할 수 있습니다 process.awk
.
tmpdir=$(mktemp -d) &&
while IFS= read -r fname; do
gpg -d "$fname" > "$tmpdir"/"$fname"
done < <(find . -name '*.gpg') &&
awk -f process.awk "$tmpdir"/* &&
rm -rf "$tmpdir"