For 루프 - Bash가 내 변수를 읽지 않습니다.

For 루프 - Bash가 내 변수를 읽지 않습니다.

나는 이 명령을 사용하여 찾은 각 파일에 대해 명령을 호출하는 작은 bash 스크립트를 만들려고 합니다 find.

스크립트가 중지되는 위치(충돌하기 쉬운 위치)를 추적하여 거기에서 다시 돌아갈 수 있기를 원합니다. 내 파일을 읽고 줄을 가져왔지만...현재 for 루프에 갇혀 있습니다. 나는 중지한 마지막 행에서 시작하여 1씩 증가하고 행 수보다 작을 때마다 이 작업을 수행하는 C 스타일 for 루프를 만들고 싶습니다. 이해합니다:

#!/bin/bash

LINES=$(wc -l < file.txt)
LASTLINE=$(grep -P '### Stop marker ###' file.txt | wc -l)
STARTFROM=$(($LINES - $LASTLINE))

for ((i = STARTFROM; i < LINES; i++));
do
    echo "we are processing file number $i"
    file=sed -n $i'p' file.txt
    ocrmypdf [some stuff] -input $file
done

file.txt내 인테리어가 어떤지 발췌해 보겠습니다.

./input_folder/hard_blurry.pdf
./input_folder/l_ordre_malte.pdf
### Stop marker ###
./input_folder/single_page.pdf
./input_folder/very_hard.pdf

이것을 실행하면 아무것도 얻지 못합니다. Bash는 루프에 전혀 들어 가지 않습니다. 정수를 직접 설정해 보았는데 작동했습니다. 이는 변수가 문자열로 읽혀졌다는 것을 알려줍니다.

나는 내 var를 작성하기 위해 다음과 같은 모든 방법을 시도했습니다.

for ((i = STARTFROM; i < LINES; i++));
for ((i = $((STARTFROM)); i < $((LINES)); i++));
for ((i = $(echo STARTFROM); i < $(echo LINES); i++));

아무것도 작동하지 않습니다. 오류도 발생하지 않은 것에 놀랐습니다. 내 운영 체제는 우분투 20.0.4입니다.

그 내용은 내가 사용하려는 파일의 경로입니다.

어떤 아이디어가 있나요? 감사해요

답변1

LASTLINE=$(grep -P '### Stop marker ###' file.txt | wc -l)

이것이 당신에게 말할 것입니다얼마나선이 패턴과 일치하지만 위치가 일치하지 않습니다. 파일에 태그가 있으면 반환합니다 . 줄 번호를 얻으려면 ( ) 1와 같은 것을 사용해야 합니다 .grep -n--line-number

file=sed -n $i'p' file.txt

file=$(sed ...)이는 아마도 명령 대체를 사용하여 캡처한 출력 이어야 합니다 sed. 그러나 루프에서 이 작업을 수행하면 각 루프 반복이 전체 파일을 읽습니다. 이는 어리석은 낭비이며 파일이 길면 시간이 오래 걸립니다.

문제는 바로 여기에 있다 쉘 루프를 사용하여 텍스트를 처리하는 것이 왜 나쁜 습관으로 간주됩니까?여기 이전 링크에서 언급했습니다. 나쁜 습관은처리, 텍스트를 수정합니다. 파일의 일부 데이터를 기반으로 명령을 실행하려면 쉘을 사용하십시오. 명령을 실행하기 위해 쉘이 존재합니다.

따라서 파일을 한 번 반복하고 셸에서 중지 마커를 감지하면 됩니다.

#!/bin/bash
i=0
while IFS= read -r line; do 
    if [[ $line == '### Stop marker ###' ]]; then
        break;
    fi
    i=$((i + 1))
    echo "line $i, do some stuff with '$line'"
done < file.txt

(이것이 Ksh-ism입니다. POSIX 쉘에서는 . 로 대체할 수 있습니다 [[ .. ]].)case

또는 외부 텍스트 처리 도구에서 중지 표시를 처리하고 셸에서 다음 명령을 실행하도록 할 수 있습니다.

#!/bin/sh
i=0
< file.txt sed -n -e '/### Stop marker ###/q' -e p |
while IFS= read -r line; do
    i=$((i + 1))
    echo "line $i, do some stuff with '$line'"
done

만약에스타일 루프를 실제로 수행하려면 for (i = 0; i < end; i++)먼저 전체 파일을 배열로 읽어 들일 수 있지만 행에 대한 무작위 액세스가 필요하지 않으면 완전히 불필요합니다. 파일 스트리밍이 훨씬 더 자연스럽습니다.

답변2

다음과 같이 seq를 사용하여 var의 범위를 얻을 수 있습니다.

#!/bin/bash
LINES=1
LASTLINE=10
for i in $(seq $LINES $LASTLINE )
do
 echo $i
done

산출:

1
2
3
4
5
6
7
8
9
10

관련 정보