私はこのコマンドを使用して見つけた各ファイルに対してコマンドを呼び出す小さな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++));
何も動作しません。エラーも発生していないことに驚きました。私のオペレーティングシステムは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
。ただし、ループでこれを行うと、各ループ反復はファイル全体を読み取ります。これは愚かな無駄であり、ファイルが長い場合は時間がかかります。
問題はここにあります。 シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?ここでは前のリンクで言及しました。悪い習慣は処理、テキストを修正します。ファイルの一部のデータに基づいてコマンドを実行するには、シェルを使用します。コマンドを実行するためのシェルが存在します。
したがって、ファイルを一度繰り返し、シェルで停止マーカーを検出するだけです。
#!/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