各行に異なるデータを出力する方法は?

各行に異なるデータを出力する方法は?

次のファイルがあります。

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

可能であれば、最後に表示された2時間の差を計算したい(変更 - 修正)。

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

パールを使用して日付::分析そして時間::期間基準寸法。は、新起源(1970年1月1日深夜)形式以降の日付をUnix秒に解析し、秒を英語表現で印刷する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)- 最も近いゼロに丸めるには、次のものを使用できます。最近秒または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 :: Durationduration()関数を代わりに使用している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

時、分、秒は短期間ではまだ「重要」と見なされますが、長期間ではそうではありません。

関連情報