I want to structure my nginx logs which look like
ip - - [18/Dec/2016:06:44:41 +0300] "GET /some/part/thing HTTP/1.1" 200 4320 "https://referrer" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"
Currently, I'm reading each line of these logs, and with grep -E -o select details I need (ip, datetime, part, http_code, bandwidth, referrer).
But this is horribly slow with amount of logs I have. Is it possible to apply regexp per entire logfile with lookbehind etc, not per line?. I also was thinking of making this on GPUs.
UPDATE:
while IFS= read -r line || [ "$line" ]; do
        cnt=$((cnt+1))
        # we will match each information separating with first space,
        # then remove that info from line for the next info
        ip=,
        datetime=,
        slug=,
        http_code=,
        chunk_size=,
        referrer=,
        # Input 1. ip address
        ip=`echo $line | grep -E -o '^\S*'` || parse_error "ip address" $1 $cnt
        line=${line//$ip}
        # remove trash - -
        trash=`echo $line | grep -E -o '\-\s\-'` || parse_error "- - trash" $1 $cnt
        line=${line//$trash}
        # Input 2. datetime
        datetime=`echo $line | grep -E -o '[0-9]{2}/[A-Za-z]+/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2}\s\+[0-9]{4}'` || parse_error "datetime" $1 $cnt
        line=${line//$datetime}
        # Input 3. slug
        slug=`echo $line | grep -o '[a-zA-Z0-9]*/mp4' | sed -e 's/\/mp4//'` || parse_error "stream slug" $1 $cnt
        # remove trash
        trash=`echo $line | grep -E -o '^.*HTTP/[0-2]{1}.[0-9]{1}"\s'` || parse_error "full HTTP GET req" $1 $cnt
        line=${line//$trash}
        # Input 4. http code
        http_code=`echo $line | grep -o '^\S*'` || parse_error "http code" $1 $cnt
        line=${line//$http_code}
        # this can be checked only here with regex above :(
        if [ $http_code != "200" ] && [ $http_code != "206" ]; then
            # continue to next line, skip this one, because only HTTP 200, 206 req are acceptable.
            continue
        fi
        # Input 5. http payload chunk size
        chunk_size=`echo $line | grep -o '^\S*'` || parse_error "chunk size" $1 $cnt
        line=${line//$chunk_size}
        # Input 6. Referrer
        referrer=`echo $line | grep -Po -m 1 '"\K[^"]*' | head -1` || parse_error "referrer" $1 $cnt
        # Handle cases when regex in Input 6 fails to match http referer, and match some trash instead
        if [[ $referrer != "http"* ]]; then
            referrer=""
        fi
        wait
        # printf "$ip,$datetime,$slug,$http_code,$chunk_size,%s\n" $referrer >> ./$3.csv || echo "[-] Can not write to .csv, something is bad at $cnt."
        string+="$ip,$datetime,$slug,$http_code,$chunk_size,$referrer\n"|| echo "[-] Can not put to string, something is bad at $cnt."
    done < "$1"
