用/ AWK减去时间

时间:2010-01-11 00:09:37

标签: awk

我想要实现的是第1章开始时间和第2章开始时间之间的差异等等,从数组中的下一个开始减去每个章节的开始时间,例如00:05:57 - 00:01:03 = 00:04:54

$ 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

有什么建议吗?

3 个答案:

答案 0 :(得分:1)

问题是你在BEGIN块中运行整个事情,所以它永远不会看到数据。只需删除“BEGIN {”和最后一个“}”,它就可以正常工作。

BEGIN块在读取任何数据之前运行,并用于初始化。 awk程序结构如下所示(BEGIN,主数据循环 - 由一个或多个块组成 - 而END都是可选的):

BEGIN { 
}
{
}
END {
}

主循环中的程序块可以有各种条件表达式,正则表达式或模式,用于选择是否执行它们。

此外,您的循环需要在最后一个字段之前停止,因为它无法在最后一个字段之后获取下一个字段:

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,":")

此外,当您发布问题“不起作用”时,信息量不大。

答案 1 :(得分: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

在awk读取输入文件之前处理BEGIN块。因此,如果将代码放在BEGIN块中,则不会处理该文件。

答案 2 :(得分: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