각 행에 다른 데이터를 출력하는 방법은 무엇입니까?

각 행에 다른 데이터를 출력하는 방법은 무엇입니까?

다음 파일이 있습니다.

File: ‘./Payment_Volume_and_Value_Report_000000501C5_2.10_2022_11_14_06_24_49.xml’
Modify: 2022-11-14 06:24:54.466847421 -0500
Change: 2022-11-14 06:25:02.166883414 -0500
  File: ‘./Payment_Volume_and_Value_Report_000000501C5_2.9_2022_11_14_06_24_54.xml’
Modify: 2022-11-14 06:24:54.740847211 -0500
Change: 2022-11-14 06:25:02.166883414 -0500
  File: ‘./Payment_Volume_and_Value_Report_000000501C5_2022_11_14_06_24_54.xml’
Modify: 2022-11-14 06:24:54.637847290 -0500
Change: 2022-11-14 06:25:02.166883414 -0500 

각 파일의 출력이 다음과 같기를 원합니다.

Payment_Volume_and_Value_Report_000000501C5_2.10_2022_11_14_06_24_49.xml
06:24:54
06:25:02

가능하다면 마지막에 표시된 두 시간 간의 차이를 계산하고 싶습니다(변경-수정).

Payment_Volume_and_Value_Report_000000501C5_2.10_2022_11_14_06_24_49.xml
00:00:08

답변1

사용그리고 GNU date명령:

while read -r attr data; do
    [[ $attr == File: ]] && echo "$data"
    [[ $attr == Modify: ]] && m="$data"
    if [[ $attr == Change: ]]; then
        c="$data"
        c_epoch=$(date -d"$c" +%s)
        m_epoch=$(date -d"$m" +%s)
        echo "$((c_epoch - m_epoch)) seconds"
     fi
done < file

산출:

‘./Payment_Volume_and_Value_Report_000000501C5_2.10_2022_11_14_06_24_49.xml’
8 seconds
‘./Payment_Volume_and_Value_Report_000000501C5_2.9_2022_11_14_06_24_54.xml’
8 seconds
‘./Payment_Volume_and_Value_Report_000000501C5_2022_11_14_06_24_54.xml’
8 seconds 

답변2

#! /usr/bin/env bash

INPUT_FILENAME="$1"

while read -r FIELD_NAME DATA; do
    # echo "REPLY=<$REPLY>"
    case "${FIELD_NAME}" in
        "File:")
            # Get only text between ‘ and ’
            FILE="${DATA#*‘}"
            FILE="${FILE%’*}"
            # Print filename
            printf "%s\n" "$FILE"
        ;;
        "Modify:")
            DATE_MODIFY="${DATA}"
            # Print date
            DATE_MODIFY_PRINT="${DATE_MODIFY#* }"
            DATE_MODIFY_PRINT="${DATE_MODIFY_PRINT%.*}"
            printf "%s\n" "${DATE_MODIFY_PRINT}"
            # Compute seconds since 01/01/1970
            SECONDS_MODIFY=$(date --date "${DATE_MODIFY}" +%s)
        ;;
        "Change:")
            DATE_CHANGE="${DATA}"
            # Print date
            DATE_CHANGE_PRINT="${DATE_CHANGE#* }"
            DATE_CHANGE_PRINT="${DATE_CHANGE_PRINT%.*}"
            printf "%s\n" "${DATE_CHANGE_PRINT}"
            # Compute seconds since 01/01/1970
            SECONDS_CHANGE=$(date --date "${DATE_CHANGE}" +%s)
            # Compute hours, minutes and seconds between two dates (assume CHANGE >= MODIFY)
            SECONDS_DIFF=$(( SECONDS_CHANGE - SECONDS_MODIFY ))
            MINUTES_DIFF=$(( SECONDS_DIFF / 60 ))
            SECONDS_DIFF=$(( SECONDS_DIFF - ( MINUTES_DIFF * 60 ) ))
            HOURS_DIFF=$(( MINUTES_DIFF / 60 ))
            MINUTES_DIFF=$(( MINUTES_DIFF - ( HOURS_DIFF * 60 ) ))
            printf "%02d:%02d:%02d\n" "$HOURS_DIFF" "$MINUTES_DIFF" "$SECONDS_DIFF"
        ;;
    esac
done < <(cat "${INPUT_FILENAME}"; echo)

산출:

./Payment_Volume_and_Value_Report_000000501C5_2.10_2022_11_14_06_24_49.xml
06:24:54
06:25:02
00:00:08
./Payment_Volume_and_Value_Report_000000501C5_2.9_2022_11_14_06_24_54.xml
06:24:54
06:25:02
00:00:08
./Payment_Volume_and_Value_Report_000000501C5_2022_11_14_06_24_54.xml
06:24:54
07:28:02
00:00:08

답변3

펄을 사용하고날짜::분석그리고시간::기간기준 치수. 는 신기원(1970년 1월 1일 자정) 형식 이후의 날짜를 유닉스 초로 구문 분석하고 초를 영어 표현으로 인쇄하는 Date::Parse모듈입니다 . 이들 중 어느 것도 Perl에 포함되어 있지 않으며 다음을 통해 설치해야 합니다.time_tTime::Duration또는 배포 패키지에서(예 apt-get install libtimedate-perl libtime-duration-perl: Debian에서:)

$ perl -MDate::Parse -MTime::Duration -lne '
  if (/^\s*File:\s*/) {
    s/^.*?: //; # remove field name
    s/^‘|’$//g; # remove quotes
    print;

  } elsif (/^\s*Modify:\s*/) {
    s/^.*?: //;
    $mod = $_;

  } elsif (/^\s*Change:\s*/) {
    s/^.*?: //;
    $change = $_;
    print duration_exact(str2time($change) - str2time($mod));
  }' file.txt
./Payment_Volume_and_Value_Report_000000501C5_2.10_2022_11_14_06_24_49.xml
7 seconds
./Payment_Volume_and_Value_Report_000000501C5_2.9_2022_11_14_06_24_54.xml
7 seconds
./Payment_Volume_and_Value_Report_000000501C5_2022_11_14_06_24_54.xml
7 seconds

이 출력은 놀라운 일이 아닙니다(초가 반올림되는 것을 제외하고).아래에int(str2time($change) - str2time($mod) + 0.5)- 가장 가까운 0으로 반올림하려면 다음을 사용할 수 있습니다.최근의초 또는 BEGIN {$Time::Duration::MILLISECOND=1};밀리초 모드를 활성화하고 가장 가까운 밀리초로 반올림하기 위해 스크립트 시작 부분에 추가됨) 그러나 Time::Duration 모듈은 수정 및 변경 타임스탬프 사이의 더 큰 시간 간격으로 해당 값을 표시합니다. 예를 들어, 마지막 변경 시간이 다음과 file.txt같다면:

Change: 2022-11-18 09:25:02.166883414 -0500

그러면 이 파일의 출력은 다음과 같습니다.

./Payment_Volume_and_Value_Report_000000501C5_2022_11_14_06_24_54.xml
4 days, 3 hours, and 7 seconds

그리고 변경 타임스탬프가 다음과 같은 경우:

Change: 2029-11-18 09:25:02.166883414 -0500

그러면 출력은 다음과 같습니다.

./Payment_Volume_and_Value_Report_000000501C5_2022_11_14_06_24_54.xml
7 years, 6 days, 3 hours, and 7 seconds

이는 second 보다 이해하기 쉽습니다 221281207.529036.

또는 스크립트가 Time::Duration duration()함수를 대신 사용하는 duration_exact()경우 기간 중 가장 중요하지 않은 부분을 반올림합니다("중요도"는 기간 크기에 따라 변경됩니다).

./Payment_Volume_and_Value_Report_000000501C5_2.10_2022_11_14_06_24_49.xml
7 seconds
./Payment_Volume_and_Value_Report_000000501C5_2.9_2022_11_14_06_24_54.xml
7 seconds
./Payment_Volume_and_Value_Report_000000501C5_2022_11_14_06_24_54.xml
7 years and 6 days

시, 분, 초는 짧은 기간 동안에는 여전히 "중요한" 것으로 간주되지만 장기간에는 그렇지 않습니다.

관련 정보