1

I was given the below script by this great community to sort the rows of information.

BEGIN {

FS=":"
PROCINFO["sorted_in"]="@val_str_asc";
}

/./ {
values[$1]=$0
}

/^$/ {
asort(values)
for (element in values)
print values[element]
print ""
delete values
}

END {

asort(values)
for (element in values)
print values[element]
}

Each block are sorted alphabetically, which is working as originally intended (shown below). Now I am asked to sort all these blocks of data (each block of data has a physical space between each other) based on the sessionStartTime. I think this is going to be alot harder since each 8-line block needs to stick together.

cabLoginID:0557CAWG0FP27K31JG7Q
loginName:john
memoryInfo:jsHeapSizeLimit:2181038080
session:cabSessionID:05P2R3PJGKG2Y2XE4NCZ
sessionStartTime:2018-10-18T13:03:00.973Z
totalJSHeapSize:36675584
usedJSHeapSize:29721040
userAgent:Mozilla/5.0

cabLoginID:05P4X6K6GFPJ7K31EJ7H
loginName:bob
memoryInfo:jsHeapSizeLimit:2181038080
session:cabSessionID:0536XLJPG7BJXRN42A0F
sessionStartTime:2018-10-11T11:37:28.195Z
totalJSHeapSize:54501376
usedJSHeapSize:35478968
userAgent:Mozilla/5.0

cabLoginID:053XCDTF8D4J6PD3BG8P
loginName:jack
memoryInfo:jsHeapSizeLimit:2217857988
session:cabSessionID:052FPBP6Q6X2XGERWHBT
sessionStartTime:2018-10-01T01:04:10.899Z
totalJSHeapSize:42358792
usedJSHeapSize:36482584
userAgent:Mozilla/5.0

Desired result:

cabLoginID:053XCDTF8D4J6PD3BG8P
loginName:jack
memoryInfo:jsHeapSizeLimit:2217857988
session:cabSessionID:052FPBP6Q6X2XGERWHBT
sessionStartTime:2018-10-01T01:04:10.899Z
totalJSHeapSize:42358792
usedJSHeapSize:36482584
userAgent:Mozilla/5.0

cabLoginID:05P4X6K6GFPJ7K31EJ7H
loginName:bob
memoryInfo:jsHeapSizeLimit:2181038080
session:cabSessionID:0536XLJPG7BJXRN42A0F
sessionStartTime:2018-10-11T11:37:28.195Z
totalJSHeapSize:54501376
usedJSHeapSize:35478968
userAgent:Mozilla/5.0

cabLoginID:0557CAWG0FP27K31JG7Q
loginName:john
memoryInfo:jsHeapSizeLimit:2181038080
session:cabSessionID:05P2R3PJGKG2Y2XE4NCZ
sessionStartTime:2018-10-18T13:03:00.973Z
totalJSHeapSize:36675584
usedJSHeapSize:29721040
userAgent:Mozilla/5.0

2

Assuming that the timestamps sort lexically in your locale, and given GNU Awk version 4.0 or later:

gawk -vRS= '
  match($0,/sessionStartTime:([^[:space:]]*)/,m) {
    a[m[1]] = $0
  } 
  END {
    PROCINFO["sorted_in"] = "@ind_str_asc" 
    for (i in a) print a[i] "\n"
  }' file

Similar approach in Perl:

perl -00 -lne '
  $h{$1} = $_ if /sessionStartTime:(\S*)/
  }{
  for $k (sort keys %h) {print $h{$k}}
' file
  • Much more elegant than my perl hack. – steve Oct 25 '18 at 21:15
  • @steve thanks - I've attempted a perl implementation of the same approach – steeldriver Oct 25 '18 at 21:24
0

This seems to do the trick. I'll try post a more readable version shortly.

$ perl -e 'while(<>){next if /^$/;push @a,$_;if(/sessionStartTime/){$k=$_}if($#a==7){$v{$k}=[@a];undef @a}}for $x(sort keys %v){for $i (0..7){print $v{$x}[$i]}print "\n"}' <input >output

Cleaner, more readable version. Functionally identical.

perl -e 'while(<>) {
             # skip any blank lines
             next if /^$/;

             # add line to array a
             push @a,$_;

             # if line holds our key value, store it 
             if(/sessionStartTime/) {
                 $k=$_;
             }

             # if we've got all 8 lines, store it in a hash, keyed on our sessionStartTime
             if($#a==7) {
                 $v{$k}=[@a];
                 undef @a;
             }
         }
         # After reaching end of file, process each key and print its 8 lines
         for $x (sort keys %v) {
             for $i (0..7) {
                 print $v{$x}[$i];
             }
             print "\n";
         }' <input  >output
  • 1
    Hi steve, I place your codes into a file, and put in the input and output. When I tried to run the script, I am getting syntax errors getting the following- First error: d:\Logs\UserLogs\Commands>PerlSort.pl Can't modify subtraction (-) in scalar assignment at D:\Logs\UserLogs\Commands\PerlSort.pl line 2, near "perl -e 'while" (Might be a runaway multi-line '' string starting on line 1) Second error: syntax error at D:\Logs\UserLogs\Commands\PerlSort.pl line 2, near ") {" Third error: syntax error at D:\Logs\UserLogs\Commands\PerlSort.pl line 19, near "}" – Kam Oct 29 '18 at 17:41
0

In bash:

declare -a LINES
declare -A BLOCKS

IFS=$'\n'

addToBlocks() {
  if [ "$EPOCH" ]
  then
    BLOCKS["$EPOCH"]="${LINES[*]}"
  else
    echo "No sessionStartTime line for this block."
  fi
}

while read LINE
do
  SSTIME="${LINE/sessionStartTime:}"
  [ "${SSTIME}" != "$LINE" ] && EPOCH="$( date +%s -d "${SSTIME%Z}" )"
  if [ "${LINE// }" == "" ]
  then
    addToBlocks
    LINES=()
    EPOCH=""
  else
    LINES+=("${LINE}")
  fi
done
addToBlocks

for TIME in $( echo "${!BLOCKS[*]}" | sort -n )
do
  echo "${BLOCKS[$TIME]}"
  echo
done

Same basic idea - bath the lines up till you reach a blank line, at which point save it in a hash keyed by datetime. Once all rows are consumed, output all the blocks ordered by hash key.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.