Bash

圍繞現有循環建構一個 for 循環,以替換使用者輸入

  • May 19, 2019

我基本上有這個腳本:

#!/bin/bash

#Asks For filname and Word
echo 'Which word are you looking for?'
read word
echo 'What's the name of the file?'
read fileName


#Searches word and parses the line-numbers 
wordOut=$(grep -i -n -w $word $fileName.srt |cut -f1 -d:)

#Sets all outputs to diffrent line numbers and saves a temp file
for word in $wordOut
do
   echo $word
done >file.tmp

#Parses lines to array, removes temp file
mapfile -t arr <file.tmp
rm file.tmp

#Declares variable for the number of array entries (not used anywhere atm)
ln=${#arr[@]}

#Subtract all array entries with one
one=1
for i in "${arr[@]}"
do
   crc=`expr $i - $one`
   echo $crc
done >two.tmp

#Subtraction result to array2
mapfile -t arr2 <two.tmp
rm two.tmp
echo ${arr2[@]}

#retrieve times
for h in "${arr2[@]}"
do 
   line=$(sed "${h}q;d" $fileName.srt)
   echo $line
done >three.tmp

#replace all commas with decimal points
sed 's/,/./g' three.tmp >four.tmp

#remove temp file 3 and parse 'decimal pointed' to array
rm three.tmp
mapfile -t arr3 <four.tmp
rm four.tmp

echo ${arr3[0]}
echo ${arr3[1]}

# converts HH:MM:SS.sss to fractional seconds
codes2seconds() (
 local hh=${1%%:*}
 local rest=${1#*:}
 local mm=${rest%%:*}
 local ss=${rest#*:}
 printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss")
)

# converts fractional seconds to HH:MM:SS.sss
seconds2codes() (
 local seconds=$1
 local hh=$(bc <<< "scale=0; $seconds / 3600")
 local remainder=$(bc <<< "$seconds % 3600")
 local mm=$(bc <<< "scale=0; $remainder / 60")
 local ss=$(bc <<< "$remainder % 60")
 printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss"
)

subtracttimes() (
 local t1sec=$(codes2seconds "$1")
 local t2sec=$(codes2seconds "$2")
 printf "%s" $(bc <<< "$t2sec - $t1sec")
)


for range in "${arr3[@]}"
do  
 mod=$(sed 's/[^0-9]//g' <<< $range)
 duration=$(subtracttimes "${range%% -->*}" "${range##*--> }")
 printf "%s\n" "ffmpeg -i $fileName.mp4 -ss ${range%% -->*} -t $duration -async 1 $word.$mod.$fileName.cut.mp4"


done >final.tmp
sudo chmod 755 final.tmp
./final.tmp
rm final.tmp

效果很好。它的作用:它在 srt 文件中搜尋具有相同名稱的 mp4 文件中的關鍵字,然後找到與該關鍵字匹配的時間戳,並將影片從起點剪切到終點。

SRT 文件,例如:

**video.srt**
1
00:00:00,000 --> 00:00:04,950
welkom bij eerste toekomst reizen dus

2
00:00:02,639 --> 00:00:05,670
onderdeel aan de achterhoekse toekomst

3
00:00:04,950 --> 00:00:07,290
stoere

4
00:00:05,670 --> 00:00:11,250
mijn heren nu al heel veel dingen

所以基本上,如果你正在尋找關鍵字“toekomst”,它會輸出兩個 mp4,一個最初開始於 00:00:00,000並結束於00:00:04,950,一個開始於00:00:02,639結束於00:00:05,670

我在同一個目錄中有多個 MP4,它們都有一個與 mp4 同名的對應 .srt 文件,它們都需要通過這個腳本執行。所以我想建構一個腳本擴展來查找所有具有相同名稱的文件,並通過腳本執行它。

所以我寫了這段程式碼來測試這個:

#!/bin/bash
cd "`dirname "$0"`"
for file in *.srt
do 
fileName="$( basename "$file" .srt)"
echo $fileName
echo $fileName.mp4
echo $fileName.srt

done >temp

它確實給出了目錄中所有 .mp4 文件和 .srt 文件的輸出:

h
h.mp4
h.srt
r
r.mp4
r.srt

因此,我圍繞現有程式碼建構了這個 for 循環,如下所示:

#!/bin/bash
cd "`dirname "$0"`"
#Asks For filname and Word
echo 'Which word are you looking for?'
read word

for file in *.srt
do 
fileName="$( basename "$file" .srt)"

#Searches word and parses the line-numbers 
wordOut=$(grep -i -n -w $word $fileName.srt |cut -f1 -d:)

#Sets all outputs to diffrent line numbers and saves a temp file
for word in $wordOut
do
   echo $word
done >file.tmp

#Parses lines to array, removes temp file
mapfile -t arr <file.tmp
rm file.tmp

#Declares variable for the number of array entries (not used anywhere atm)
ln=${#arr[@]}

#Subtract all array entries with one
one=1
for i in "${arr[@]}"
do
   crc=`expr $i - $one`
   echo $crc
done >two.tmp

#Subtraction result to array2
mapfile -t arr2 <two.tmp
rm two.tmp
echo ${arr2[@]}

#retrieve times
for h in "${arr2[@]}"
do 
   line=$(sed "${h}q;d" $fileName.srt)
   echo $line
done >three.tmp

#replace all commas with decimal points
sed 's/,/./g' three.tmp >four.tmp

#remove temp file 3 and parse 'decimal pointed' to array
rm three.tmp
mapfile -t arr3 <four.tmp
rm four.tmp

echo ${arr3[0]}
echo ${arr3[1]}

# converts HH:MM:SS.sss to fractional seconds
codes2seconds() (
 local hh=${1%%:*}
 local rest=${1#*:}
 local mm=${rest%%:*}
 local ss=${rest#*:}
 printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss")
)

# converts fractional seconds to HH:MM:SS.sss
seconds2codes() (
 local seconds=$1
 local hh=$(bc <<< "scale=0; $seconds / 3600")
 local remainder=$(bc <<< "$seconds % 3600")
 local mm=$(bc <<< "scale=0; $remainder / 60")
 local ss=$(bc <<< "$remainder % 60")
 printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss"
)

subtracttimes() (
 local t1sec=$(codes2seconds "$1")
 local t2sec=$(codes2seconds "$2")
 printf "%s" $(bc <<< "$t2sec - $t1sec")
)


for range in "${arr3[@]}"
do  
 mod=$(sed 's/[^0-9]//g' <<< $range)
 duration=$(subtracttimes "${range%% -->*}" "${range##*--> }")
 printf "%s\n" "ffmpeg -i $fileName.mp4 -ss ${range%% -->*} -t $duration -async 1 $word.$mod.$fileName.cut.mp4"


done >final.tmp
sudo chmod 755 final.tmp
./final.tmp
rm final.tmp

done

第一次執行時,第一個文件給出了正確的輸出 mp4,但之後它以某種方式對變數進行了洗牌,我無法獲得正確的輸出。

我自己通過使用另一個腳本並將變數導出到主腳本來修復它,所以最後我使用了這兩個腳本。 主腳本:

#!/bin/bash
echo 'Welk woord zoek je?'
read word
export word

for file in *.srt
do

fileName="$( basename "$file" .srt)"
export fileName
./actualScript

done

實際腳本:

#!/bin/bash
#Asks For filname and Word

#Searches word and parses the line-numbers 
wordOut=$(grep -i -n -w $word $fileName.srt |cut -f1 -d:)

#Sets all outputs to diffrent line numbers and saves a temp file
for word in $wordOut
do
   echo $word
done >file.tmp

#Parses lines to array, removes temp file
mapfile -t arr <file.tmp
rm file.tmp

#Declares variable for the number of array entries (not used anywhere atm)
ln=${#arr[@]}

#Subtract all array entries with one
one=1
for i in "${arr[@]}"
do
   crc=`expr $i - $one`
   echo $crc
done >two.tmp

#Subtraction result to array2
mapfile -t arr2 <two.tmp
rm two.tmp
echo ${arr2[@]}

#retrieve times
for h in "${arr2[@]}"
do 
   line=$(sed "${h}q;d" $fileName.srt)
   echo $line
done >three.tmp

#replace all commas with decimal points
sed 's/,/./g' three.tmp >four.tmp

#remove temp file 3 and parse 'decimal pointed' to array
rm three.tmp
mapfile -t arr3 <four.tmp
rm four.tmp

echo ${arr3[0]}
echo ${arr3[1]}

# converts HH:MM:SS.sss to fractional seconds
codes2seconds() (
 local hh=${1%%:*}
 local rest=${1#*:}
 local mm=${rest%%:*}
 local ss=${rest#*:}
 printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss")
)

# converts fractional seconds to HH:MM:SS.sss
seconds2codes() (
 local seconds=$1
 local hh=$(bc <<< "scale=0; $seconds / 3600")
 local remainder=$(bc <<< "$seconds % 3600")
 local mm=$(bc <<< "scale=0; $remainder / 60")
 local ss=$(bc <<< "$remainder % 60")
 printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss"
)

subtracttimes() (
 local t1sec=$(codes2seconds "$1")
 local t2sec=$(codes2seconds "$2")
 printf "%s" $(bc <<< "$t2sec - $t1sec")
)


for range in "${arr3[@]}"
do  
 mod=$(sed 's/[^0-9]//g' <<< $range)
 duration=$(subtracttimes "${range%% -->*}" "${range##*--> }")
 printf "%s\n" "ffmpeg -i $fileName.mp4 -ss ${range%% -->*} -t $duration -async 1 $word.$mod.$fileName.cut.mp4"


done >final.tmp
sudo chmod 755 final.tmp
./final.tmp
rm final.tmp

引用自:https://unix.stackexchange.com/questions/427677