如何让每一行输出不同的数据?

如何让每一行输出不同的数据?

我有以下文件:

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

使用和 GNUdate命令:

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

使用 Perl 和日期::解析时间::持续时间模块。 Date::Parse是一个用于将日期解析为 unixtime_t自从纪元以来的秒数(1970 年 1 月 1 日午夜)格式的模块,也是Time::Duration一个用于将秒打印为英文表达式的模块。这些都不包含在 perl 中,它们需要通过安装或来自发行版包(例如在 Debian 上apt-get install libtimedate-perl libtime-duration-perl:)

$ 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)-如果您希望四舍五入到四舍五入,则可以使用最近的第二个,或者添加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

这比秒更容易理解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

小时、分钟和秒对于短持续时间仍然被认为是“重要的”,但对于长持续时间来说并不重要。

相关内容