특정 데이터 행을 기준으로 데이터 블록 정렬

특정 데이터 행을 기준으로 데이터 블록 정렬

이 훌륭한 커뮤니티에서는 정보 행을 정렬할 수 있는 아래 스크립트를 제공했습니다.

시작 {

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

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

/^$/ {
asort(values)
for (값의 요소)
인쇄 값 [요소]
인쇄 ""
값 삭제
}

끝 {

asort(value)
for (값의 요소)
print value[element]
}

각 블록은 알파벳순으로 정렬되어 원래 의도한 대로 작동합니다(아래 참조). 이제 sessionStartTime을 기준으로 이러한 모든 데이터 청크(각 청크 사이의 물리적 공간 포함)를 정렬하라는 요청을 받았습니다. 나는 이것이 훨씬 더 어려울 것이라고 생각했습니다. 왜냐하면 각각의 8줄 블록을 함께 접착해야 하기 때문입니다.

cabLoginID: 0557CAWG0FP27K31JG7Q
로그인: john
memoryInfo: jsHeapSizeLimit: 2181038080
세션: cabSessionID: 05P2R3PJGKG2Y2XE4NCZ
세션 시작 시간: 2018-10-18T13:03:00.973Z
총 JSHeapSize: 36675584
JSHeapSize 사용: 29721040
userAgent: Mozilla/5.0

cabLoginID: 05P4X6K6GFPJ7K31EJ7H
로그인: bob
메모리 정보: jsHeapSizeLimit: 2181038080
세션: cabSessionID: 0536XLJPG7BJXRN42A0F
세션 시작 시간: 2018-10-11T11:37:28.195Z
총 JSHeapSize: 54501376
JSHeapSize 사용: 35478968
userAgent: Mozilla/5.0

cabLoginID:053XCDTF8D4J6PD3BG8PLogin
:jack
memoryInfo:jsHeapSizeLimit:2217857988
세션:cabSessionID:052FPBP6Q6X2XGERWHBT
세션 시작 시간: 2018-10-01T01:04:10.899Z
총 JSHeapSize: 42358792
사용된 JSHeapSize: 36482584
userAgent: Mozilla/5.0

원하는 결과:

cabLoginID:053XCDTF8D4J6PD3BG8PLogin
:jack
memoryInfo:jsHeapSizeLimit:2217857988
세션:cabSessionID:052FPBP6Q6X2XGERWHBT
세션 시작 시간: 2018-10-01T01:04:10.899Z
총 JSHeapSize: 42358792
사용된 JSHeapSize: 36482584
userAgent: Mozilla/5.0

cabLoginID: 05P4X6K6GFPJ7K31EJ7H
로그인: bob
메모리 정보: jsHeapSizeLimit: 2181038080
세션: cabSessionID: 0536XLJPG7BJXRN42A0F
세션 시작 시간: 2018-10-11T11:37:28.195Z
총 JSHeapSize: 54501376
JSHeapSize 사용: 35478968
userAgent: Mozilla/5.0

cabLoginID: 0557CAWG0FP27K31JG7Q
로그인: john
memoryInfo: jsHeapSizeLimit: 2181038080
세션: cabSessionID: 05P2R3PJGKG2Y2XE4NCZ
세션 시작 시간: 2018-10-18T13:03:00.973Z
총 JSHeapSize: 36675584
JSHeapSize 사용: 29721040
userAgent: Mozilla/5.0

답변1

타임스탬프가 해당 로캘에서 어휘적으로 정렬되어 있고 GNU Awk 버전 4.0 이상이 제공되었다고 가정합니다.

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

Perl에서도 비슷한 방법:

perl -00 -lne '
  $h{$1} = $_ if /sessionStartTime:(\S*)/
  }{
  for $k (sort keys %h) {print $h{$k}}
' file

답변2

이것이 트릭을 수행하는 것 같습니다. 조만간 좀 더 읽기 쉬운 버전을 게시하도록 노력하겠습니다.

$ 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

더 깨끗하고 읽기 쉬운 버전입니다. 기능은 동일합니다.

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

답변3

배쉬에서:

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

동일한 기본 아이디어 - 빈 행에 도달할 때까지 행을 반복하고, 그 시점에서 날짜/시간으로 키가 지정된 해시에 저장합니다. 모든 행이 소비되면 해시 키로 정렬된 모든 청크를 출력합니다.

관련 정보