从bash中分出时间戳/键/值对

时间:2014-12-05 19:39:30

标签: linux bash

嗨我这个文件充满了数据;时间戳基本上是行的开头。我需要分解文件并单独打印每一行。如何仅使用bash和(如果需要)标准UNIX工具(sed,awk等)实现此目的?

时间戳字段从08:30:00:324810:向前...示例17:30:00:324810 :.时间戳后的字段数量不同;所以可能有1到x个字段。所以我需要找到时间戳格式,然后插入分页符。

08:30:00:324810: usg_07Y  BidYield=1.99788141 Bid=99.20312500 08:30:00:325271: usg_07Y
AskYield=1.98578274 Ask=99.28125000 08:30:00:325535: usg_10Y  Ask=0.00000000 08:30:01:324881: 
usg_07Y  BidYield=2.02938740 AskYield=1.97127853 Bid=99.00000000 Ask=99.37500000 08:30:01:377021:
usg_05Y  Bid=0.00000000 Ask=0.00000000 

提前感谢你 马特

2 个答案:

答案 0 :(得分:1)

这是相当微不足道的。将文件读入array,找到timestamp,然后输出newline

#!/bin/bash

set -f                          # inhibit globbing (filename expansion)
declare -i cnt=0                # simple counter

a=( $(<"$1") )                  # read file into array
for i in "${a[@]}"; do          # for each word in file
    if [ "$cnt" -gt 0 ]; then   # test counter > 0
        # if last char ':', then output newline before word
        [ ${i:(-1):1} = ':' ] && printf "\n%s" "${i}" || printf " %s" "$i"
    else
        printf "%s" "$i"        # if first word, just print.
    fi
    ((cnt++))
done
printf "\n"

使用/输出:

$ bash parsedtstamp.sh filename.txt
08:30:00:324810: usg_07Y BidYield=1.99788141 Bid=99.20312500
08:30:00:325271: usg_07Y AskYield=1.98578274 Ask=99.28125000
08:30:00:325535: usg_10Y Ask=0.00000000
08:30:01:324881: usg_07Y BidYield=2.02938740 AskYield=1.97127853 Bid=99.00000000 Ask=99.37500000
08:30:01:377021: usg_05Y Bid=0.00000000 Ask=0.00000000

我添加了一个计数器var,只输出换行符,如果不是第一个单词。


备用版本,可避免临时阵列存储(对于大型文件)

虽然Bash中的数组大小没有限制,但如果发现自己解析了百万行文件,最好避免将所有行存储在内存中。这可以通过简单地处理从文件中读取的行来完成。这只是一种不使用数组进行中间存储的方法:

#!/bin/bash

set -f                              # inhibit globbing (filename expansion)
declare -i cnt=0                    # simple counter

# read each line in file
while read -r line_entries || [ -n "$line_entries" ]; do
    for i in $line_entries; do      # for each word in line (no quotes for word splitting)
        if [ "$cnt" -gt 0 ]; then   # test counter > 0
            # if last char ':', then output newline before word
            if [ ${i:(-1):1} = ':' ]; then
                printf "\n%s" "${i}"
            else
                printf " %s" "$i"
            fi
        else
            printf "%s" "$i"        # if first word, just print.
        fi
        ((cnt++))                   # increment counter
    done
done <"$1"

printf "\n"

答案 1 :(得分:0)

一种awk方式

awk -vORS="" '{for(i=1;i<=NF;i++)if($i~/:$/&&x++)$i="\n"$i}$NF=$NF" "
               END{print "\n"}' file

将输出记录sep设置为空 循环通过领域。
如果字段最后一个字符为:,则它会在字段前添加换行符 添加空格到最后一个字段,以防它是一个日期,以防止冒号和下一个字段之间没有空格 最后打印换行符。