특정 값으로 파일을 선택하도록 다음 bash 코드를 어떻게 수정합니까? 예를 들어, selcnt=3
파일 3개마다 패턴이 검색되고, selcnt=5
파일 5개마다 패턴이 검색되는 식입니다.
grep -r -l "${isufx[@]}" -e "$ptrn" -- "${fdir[@]}" |
while read f; do
echo -e $(tput setaf 46)"==> $f <==\n"$(tput sgr0)
grep -ni "${ictx[@]}" -e "$ptrn" -- "$f"
echo ""
done
목적은 검색 프로세스 속도를 높이면서 출력을 한 번에 하나의 파일로 분할하는 것입니다. 프로세스 속도를 높이는 한 가지 방법은 예를 들어 파일을 건너뛰는 방식으로 실행마다 다른 파일을 처리하는 것입니다.
Run 1: Start from file 1 and skipping two files;
Run 2: Start from file 2 and skipping two files;
Run 3: Start from file 2 and skipping two files.
첫 번째 시도로 나는
ist=1; isk=2
grep --null -r -l "${isufx[@]}" -e "$ptrn" -- "${fdir[@]}" |
sed -z '${ist}~${isk}!d' |
while IFS= read -rd '' fl; do
printf '%s\n\n' "${grn}==> $fl <==${sgr}"
grep -ni "${ictx[@]}" -e "$ptrn" -- "$fl"
done
하지만 오류가 발생해요
sed: -e expression #1, char 0: unmatched `{'
답변1
출력에서 세 번째 파일을 모두 선택하려면 먼저 임의의 파일 경로(추가 / 옵션 ) grep -l
를 처리할 수 있도록 NUL로 구분된 목록으로 전환해야 한다는 점에 유의한 후 다음을 선택할 수 있습니다.--null
-Z
grep
gawk -v RS='\0' -v ORS='\0' 'NR ~ 3 == 1'
sed -z '1~3!d' # assuming GNU sed
perl -0ne 'print if $. % 3 == 0'
그런 다음 해당 출력을 반복하려면 다음과 같이 합니다(zsh 또는 bash 사용).
green=$(tput setaf 46) sgr0=$(tput sgr0)
while IFS= read -rd '' file; do
printf '%s\n\n' "$green==> $file <==$sgr0"
...
done
echo -e
파일 이름에 나타나는 백슬래시 문자가 깨질 수 있으므로 사용하지 마십시오 .
따라서 그것들을 하나로 합치십시오:
green=$(tput setaf 46) sgr0=$(tput sgr0)
grep --null -r -l "${isufx[@]}" -e "$ptrn" -- "${fdir[@]}" |
sed -z '1~3!d' |
while IFS= read -rd '' file; do
printf '%s\n\n' "$green==> $file <==$sgr0"
grep -ni "${ictx[@]}" -e "$ptrn" -- "$file"
done
그러나 요점이 이 루프 중 3개를 병렬로 실행하고 각 루프가 3개의 배치 중 1개를 처리하는 것이라면 이것이 GNU와 같은 용도입니다 parallel
.
grep --null -r -l "${isufx[@]}" -e "$ptrn" -- "${fdir[@]}" |
PARALLEL_SHELL=bash \
GREEN=$(tput setaf 46) \
SGR0=$(tput sgr0) \
PTRN=$ptrn \
parallel -m0kj3 '
for file in {}; do
printf "%s\n\n" "$GREEN==> $file <==$SGR0"
grep -ni '"${ictx[@]@Q}"' -e "$PTRN" -- "$file"
done'
여기서 스칼라 변수는 환경 변수를 통해 전달됩니다. 그렇지 않으면 ${param@Q}
bash-4.4+를 사용하여 배열 정의가 내부 bash 인스턴스에 전달됩니다(여기서는 값에 parallel
, {}
... 와 같은 특수 문자열이 포함되어 있지 않다고 가정 {.}
).
또는 위의 제한 사항을 피하는 것이 더 좋습니다.
grep --null -r -l "${isufx[@]}" -e "$ptrn" -- "${fdir[@]}" |
PARALLEL_SHELL=bash TRANSFER_CODE=$(
green=$(tput setaf 46) sgr0=$(tput sgr0)
typeset -p green sgr0 ptrn ictx
) parallel -m0kj3 '
eval "$TRANSFER_CODE"
for file in {}; do
printf "%s\n\n" "$green==> $file <==$sgr0"
grep -ni "${ictx[@]" -e "$ptrn" -- "$file"
done'
이번에 사용된 출력은 typeset -p
이러한 모든 변수(배열 또는 비배열)의 정의를 내부적으로 전송합니다 bash
.
parallel
3개의 bash
셸이 병렬로 시작되며, 각 셸은 파일의 1/3을 처리하고 마지막에 출력을 순차적으로 다시 어셈블합니다.
어쨌든 병목 현상이 I/O(디스크에서 데이터를 읽는 속도)인 경우 이러한 작업을 병렬로 실행하는 것은 도움이 되지 않습니다.