파일의 연속 라인 사이의 변경 사항 표시

파일의 연속 라인 사이의 변경 사항 표시

파일의 행이 어떻게 변경되었는지 쉽게 확인할 수 있는 방법이 있습니까? 예를 들어, 다음 "my.log" 파일이 있다고 가정해 보겠습니다.

cpu1 cpu2 cpu3 cpu4
   5    3    3    6
   5    3    3    6
   5    0    3    6
   3    0    6    6
   5    3    3    0

명령줄에 "cat my.log | showchanges"와 같은 내용을 입력하면 다음과 같은 내용이 표시됩니다.

cpu1 cpu2 cpu3 cpu4
   5    3    3    6
   "    "    "    "
   "    0    "    "
   3    "    6    "
   5    3    3    0

이상적으로 "showchanges"는 공백을 열 구분 기호로 탐욕스럽게 처리하여 이를 수행하지만 세부 사항에 대해서는 매우 유연합니다. 열이 많을 때 변경 사항을 쉽게 확인하고 싶습니다. 또한 전혀 변경되지 않는 행을 생략하는 것이 궁극적으로 더 좋습니다.

답변1

awk '{ bak=$0; for(i=1; i<=NF; i++)$i=($i==tmp[i]?"-":$i)
       split(bak, tmp)
}1' infile

cpu1 cpu2 cpu3 cpu4
5 3 3 6
- - - -
- 0 - -
3 - 6 -
5 3 3 0

레코드 들여쓰기를 유지하려면(필드 너비 4):

awk '{ bak=$0; for(i=1; i<=NF; i++)$i=sprintf("%4s", ($i==tmp[i]?"-":$i))
       split(bak, tmp)
}1' infile

cpu1 cpu2 cpu3 cpu4
   5    3    3    6
   -    -    -    -
   -    0    -    -
   3    -    6    -
   5    3    3    0

답변2

사실입니다. 이것은 코딩 서비스가 아닙니다. 그러나 작업이 쉽거나 재미있다면 우리 중 일부는 조치를 취할 것입니다. (-;

프로그래밍 방법을 모른다고 가정하면 sed다음과 같은 줄 길이를 가진 실제 한 줄짜리 코드는 사용할 수 없습니다.

sed -E -e '1h;1n;H;x;s/$|\n/_&/g;:1' -e 's/( +)([^ ]+)_(.*)\1\2_/_\1\2\3_\1"/;t1' -e '/^_/!s/( +[^ ]+)_/_\1/g;/^_/!b1' -e 's/.*_//'

파일의 일관성을 유지하기 위해 첫 번째 줄 시작 부분에 공백을 추가했습니다(다른 줄도 공백으로 시작함). 아이디어는 동일한 레코드를 확인하기 위한 마커로 밑줄(또는 밑줄이 파일의 일부일 수 있는 경우 다른 마커)을 사용하여 이전 공간에 이전 줄을 유지하고 한 쌍의 줄을 처리하는 것입니다.

참고: 확장 정규식에서는 역참조가 정의되지 않았기 때문에 이것이 실제로 표준은 아니지만 기본 정규식으로 작성하면 정말 혼란스러워 보입니다. 어쨌든 sedERE에서 역참조를 지원하지 않는 버전 은 없습니다 .

더 읽기 쉽게 만들어 보겠습니다.

sed -E '1h;1n;# handle the first line
  H;x;# add current line to hold space and exchange buffers to store the current line
  s/$|\n/_&/g;# now add the underscore add the end of the lines
  :1
  s/( +)([^ ]+)_(.*)\1\2_/_\1\2\3_\1"/;# if the record at the _ is repeated in the new line, replace it with a quote, advance the _ and repeat
  t1
  /^_/!s/( +[^ ]+)_/_\1/g;# the t did not loop, so if we are not the done, advance the _ and process if necessary
  /^_/!b1
  s/.*_//;# finally remove everything before the processed line'

답변3

watch -d tail my.log
(default parameters, equivalent to : watch -d -n 2 tail -n 10 my.log)

watch -d -n 5 tail -n 15 my.log
At 5 seconds interval, watch last 15 lines from my.log

man watch
   -d, --differences [permanent]
          Highlight  the differences between successive updates.  
          Option will read optional argument that changes highlight to be permanent, 
          allowing to see what has changed at least once since first iteration.

   -n, --interval seconds
          Specify  update interval.  
          The command will not allow quicker than 0.1 second interval,
          in which the smaller values are converted. 
          Both '.' and ',' work for any locales.

man tail
   -n, --lines=[+]NUM
          output the last NUM lines, instead of the last 10; 
          or use -n +NUM to output starting with line NUM

답변4

bash 스크립트와 함께 예제를 사용하십시오. 이름을 myscript.sh로 지정했습니다.

#!/bin/bash
FILENAME=$1
LINEAS=$(cat "$FILENAME" | wc -l)
N=1
while read LINE
do
if [[ $N -gt 1 ]]; then
    if [[ $N -eq 2 ]]; then
        echo $LINE
        PREVIA=$LINE
    else
        L1=$(echo "$LINE" |awk -F' ' '{print $1}')
        L2=$(echo "$LINE" |awk -F' ' '{print $2}')
        L3=$(echo "$LINE" |awk -F' ' '{print $3}')
        L4=$(echo "$LINE" |awk -F' ' '{print $4}')
        P1=$(echo "$PREVIA" |awk -F' ' '{print $1}')
        P2=$(echo "$PREVIA" |awk -F' ' '{print $2}')
        P3=$(echo "$PREVIA" |awk -F' ' '{print $3}')
        P4=$(echo "$PREVIA" |awk -F' ' '{print $4}')
        if [[ $L1 -eq $P1 ]]; then
            R1="-"
        else
            R1="$L1"
        fi
        if [[ $L2 -eq $P2 ]]; then
            R2="-"
        else
            R2="$L2"
        fi
        if [[ $L3 -eq $P3 ]]; then
            R3="-"
        else
            R3="$L3"
        fi
        if [[ $L4 -eq $P4 ]]; then
            R4="-"
        else
            R4="$L4"
        fi
        echo $R1" "$R2" "$R3" "$R4
        PREVIA=$LINE
    fi
fi
let "N=N+1"
done < $FILENAME

스크립트 실행

./myscript.sh my.log

결과 :

5 3 3 6
- - - -
- 0 - -
3 - 6 -

관련 정보