2010-01-11 94 views
0

我想要實現的是第1章開始時間和第2章開始時間之間的差別等等,從數組中的下一個減去每個章節的開始時間。 0時05分57秒 - 0點01分03秒= 0時04分54秒減去時間W/AWK

$ cat ChapterStart 
00:00:00 00:01:03 00:05:57 00:08:27 00:11:58 00:14:50 00:20:19 00:25:06 00:33:17 00:38:21 00:42:30 00:46:11 00:51:33 01:00:04 01:00:56 01:04:15 01:09:13 01:16:51 01:20:03 01:27:58 

這根本不起作用:

#!/bin/bash 
awk 'BEGIN{ 
{ 
for(i=1;i<=NF;i++){ 
    m=split($i,t,":") 
    n=split($(i+1),w,":") 
    chap = (t[1]*3600) + (t[2]*60) + t[3] 
    chap_next = (w[1]*3600) + (w[2]*60) + w[3] 
    duration = (chap_next - chap) 
    print $duration 
    } 
} 
}'ChapterStart 

有什麼建議?

回答

1

問題是,您正在運行BEGIN塊中的所有內容,因此它永遠不會看到數據。只要刪除「BEGIN {」和最後一個「}」,它應該可以正常工作。

BEGIN塊在任何數據讀取之前運行並用於初始化。 AWK程序結構看起來像這樣(BEGIN,主數據循環 - 由一個或多個塊的 - 和END各自可選):

BEGIN { 
} 
{ 
} 
END { 
} 

在主循環中,程序塊可以具有各種condional表達式的正則表達式或者選擇它們是否被執行的模式。

此外,你的循環需要,因爲它不能獲得在最後的下一個停止的最後一個前場:

for(i=1;i<NF;i++){ 

除非你刪除美元符號這條線將不起作用:

print $duration 

既然你不這樣做與split返回值什麼可以消除變量賦值或重用變量:

split($i,t,":") 
split($(i+1),w,":") 

m=split($i,t,":") 
m=split($(i+1),w,":") 

此外,當您張貼問題「不工作」是不是很豐富。

0

正確的代碼應該是

awk '{ 
for(i=1;i<NF;i++){ 
    m=split($i,t,":") 
    n=split($(i+1),w,":") 
    chap = (t[1]*3600) + (t[2]*60) + t[3] 
    chap_next = (w[1]*3600) + (w[2]*60) + w[3] 
    duration = (chap_next - chap) 
    print duration 
} 
}' file 

塊被處理的BEGIN由AWK讀取輸入文件之前。因此,如果您將代碼放入BEGIN塊中,則不會處理該文件。

+0

看到我關於循環結束測試的答案。 – 2010-01-11 02:52:19

0

此外,當您發佈問題 「不起作用」是不是很有用的信息。

你當然是對的。也許最好是說「什麼也不做」,因爲沒有發生任何事情,所以這會非常準確。 =)

感謝你們倆。

儘管我還沒有完全理解awk的許多神祕方法,但我確實找到了一個更簡單的(對我來說)解決方案,並在這個過程中學到了一點兒。這有效,但肯定可以做得更好。

#!/bin/bash 
#~ Prelude to a DVD audio ripper. 
#~ This simply prints Audio ID's & start/end/duration times for the longest DVD title. 

MPLAYER=$(which mplayer) 
DRIVE=${1:-/dev/dvd} ## Check for softlink to DVD drive, otherwise let user specify 
    if ! [ -b "$DRIVE" ]; then 
     read -p "DVD drive name? (/dev/scd0 for example): " DRIVE 
    fi 

#~ Find, then scan the longest title 

    LTITLE=$($MPLAYER dvd:// -dvd-device $DRIVE -identify -vo null -ao null -nolirc -nojoystick \ 
    -frames 0 2>/dev/null| awk '/ID_DVD_TITLE/'|awk '/LENGTH/'|sort -n -t = -k 2 |tail -1 |cut -f 4 -d _) 
    MPLAYER_OUT=$($MPLAYER dvd://$LTITLE -dvd-device $DRIVE -identify -vo null -ao null -nolirc \ 
    -nojoystick -frames 0 2>/dev/null) ## mplayer tells us about the longest title on the disc/image 

#~ Set some variables per $MPLAYER_OUT 

    VID=$(echo "$MPLAYER_OUT"|awk '/ID_DVD_VOLUME_ID=/{sub(/ID_DVD_VOLUME_ID=/,"");print}') ## Get the DVD Volume ID 
    CHAPTERS=$(echo "$MPLAYER_OUT"|awk '/ID_CHAPTERS/ {sub(/ID_CHAPTERS=/,"");print}') ## Total number of chapters in longest title 
    ChapStart=($(echo "$MPLAYER_OUT"|awk '/CHAPTERS:/'|sed 's/CHAPTERS://; s/,/\n /g')) 
    ChapEnd=($(echo "$MPLAYER_OUT"|awk '/CHAPTERS:/'|sed 's/CHAPTERS://; s/,/\n /g')) 
    DiscTimeTotal=$(echo "$MPLAYER_OUT" |awk '/ID_DVD_TITLE_'$LTITLE'_LENGTH/ {sub(/ID_DVD_TITLE_'$LTITLE'_LENGTH=/,"");print}') 
    DiscTime=$(echo "$MPLAYER_OUT" |echo - |awk '{printf "%02d:%02d:%02d","'"$DiscTimeTotal"'"/(60*60),"'"$DiscTimeTotal"'"%(60*60)/60,"'"$DiscTimeTotal"'"%60}';echo) ## Converted to HH:MM:SS 
    Disc=$(date +%s -d "$DiscTime") ## Convert to seconds since 1970-01-01 - this becomes that last ChapTimeEnd array element 
    Streams=$(echo "$MPLAYER_OUT" |awk '/audio stream/'|sed 's/.$//;s/language/Language/'|awk '{ print "AID: " $10, "Format: " $5, $7, $8, $6 }') 

#~ Convert ChapStart HH:MM:SS to ChapTimeStart seconds since 1970-01-01 

for ((s=0; s<=$CHAPTERS; s++)) 
    do 
     ChapTimeStart[$s]=$(date +%s -d "${ChapStart[$s]}") 
     ChapTimeEnd[$s]=$(date +%s -d "${ChapEnd[$s]}") 
done 

    unset ChapTimeEnd[0] ## Remove the first chapter start time (always 00:00:00) in the array 
    ChapTimeEnd[$CHAPTERS]=$DisC## Add $Disc as last array element 
    ChapTimeEnd=("${ChapTimeEnd[@]}") ## Pack the array 

    unset ChapEnd[0] ## Offset the time differences - this is printed to screen as "End: HH:MM:SS" 
    ChapEnd[$CHAPTERS]=$DiscTime ## Add $DiscTime as last array element 
    ChapEnd=("${ChapEnd[@]}")  ## Pack the array 

#~ Provide some feedback: 

echo 
echo " --- DVD Volume ID ---";echo 
echo "$VID";echo 
echo " --- Longest Title ----";echo 
echo "Title $LTITLE is longest with $CHAPTERS Chapters" 
echo "Title $LTITLE Length: $DiscTime";echo 
echo " ---- Audio ID's ----";echo 
echo "$Streams";echo 

#~ Print start/end/duration 

echo " ---- Chapters ----";echo 
for ((t=0; t<$CHAPTERS; t++)) 
    do TimeDiff[$t]=$((${ChapTimeEnd[$t]} - ${ChapTimeStart[$t]})) ## Do the integer math with values expressed as seconds since 1970-01-01 
     Duration=$(echo - |awk '{printf "%02d:%02d:%02d","'"${TimeDiff[$t]}"'"/(60*60),"'"${TimeDiff[$t]}"'"%(60*60)/60,"'"${TimeDiff[$t]}"'"%60}';echo) 
    echo "Chapter: `printf "%02d" $(($t+1))` Start: "${ChapStart[$t]}" End: "${ChapEnd[$t]}" Duration: $Duration" 
done 
echo "_____________________________________________________________" 
echo 
+0

'sed'可以做'grepping',你正在使用'awk'。而不是'awk'/ CHAPTERS:/'| sed's /.../ g'只需執行'sed -n'/SYSs:/s/.../gp'。有趣的是,您正在使用'awk'在其他地方執行'grep'工作。但是,您應該知道可以使用'awk'來完成許多使用'sed'的工作。在我的系統中,Bash的內置'echo'或外部'/ bin/echo'都不接受標準輸入,因此您的'echo $ var | echo -'只會回顯沒有變量內容的短劃線。在某些情況下,您可以將'awk'腳本放入BEGIN塊中,而不是將'echo -'輸入它。 – 2010-02-23 14:22:07

+0

你應該使用'awk'變量而不是複雜的引用。閱讀和維護更容易。 'awk -v TimeDiff = $ {TimeDiff [$ t]}'{printf ... TimeDiff /(60 * 60),TimeDiff%(60 * 60)/ 60 ...' – 2010-02-23 14:26:24