For 循环 - Bash 没有读取我的变量

For 循环 - Bash 没有读取我的变量

我正在尝试制作一个小 bash 脚本,该脚本对使用该命令找到的文件中的每个文件调用一个命令find

我希望能够跟踪脚本停止的位置(它往往会崩溃),以便我可以从那里返回。我设法读取我的文件,获取行,...但目前我陷入了 for 循环。我想做一个 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++));

没有任何效果。我很惊讶也没有抛出任何错误。我的操作系统是ubuntu 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。但是,如果您在循环中执行此操作,则每次循环迭代都会读取整个文件,这是一种愚蠢的浪费,并且如果文件很长,则需要很长时间。

这就是问题所在 为什么使用 shell 循环处理文本被认为是不好的做法?之前链接在这里提到的。请注意,不好的做法是加工,修改文本。使用 shell 根据文件中的某些数据运行命令就可以了; shell 的存在是为了运行命令。

因此,只需循环一次文件并检测 shell 中的停止标记:

#!/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 shell 中[[ .. ]]替换为。)case

或者,让一些外部文本处理工具处理停止标记并让 shell 运行命令:

#!/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

相关内容