2010-01-11 78 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