이 bash 스크립트를 더 빠르게 실행하는 데 도움이 필요합니다.

이 bash 스크립트를 더 빠르게 실행하는 데 도움이 필요합니다.

로컬 로그 파일을 가져오고, 각 줄, 카드의 ID 및 IO 유형을 읽고, 관련 데이터 문자열을 추출하고, 해당 문자열을 정의 파일과 비교하고, 각 비트에 T 또는 F 값을 할당하는 스크립트가 있습니다. 그런 다음 사람이 읽을 수 있는 비트 이름과 T/F 값이 포함된 새 로그 파일을 생성합니다.

다음은 제가 입력한 몇 가지 예시 라인입니다:

[09:00:15] STA8   09:58:47 28DEC23  I/O In  07 0000  0000  0000  0000
[09:00:15] STA8   09:58:47 28DEC23  I/O In  08 0000  0010  0000  0000
[09:00:15] STA8   09:58:47 28DEC23  I/O Out 07 --00  ++++  ++++  ++00
[09:00:15] STA8   09:58:47 28DEC23  I/O Out 08 ++++  ++0+  ++++  0000

다음은 몇 가지 출력 샘플 라인입니다.

[09:00:15] STA8   09:58:47 28DEC23  I/O In  07 1:F 2:F 3:F ...
[09:00:15] STA8   09:58:47 28DEC23  I/O In  08 1:F 2:F 3:F ...
[09:00:15] STA8   09:58:47 28DEC23  I/O Out 07 1:F 2:F 3:F 4:F 5:T 6:T 7:T  8:T 9:T 10:T 11:T 12:T ...
[09:00:15] STA8   09:58:47 28DEC23  I/O Out 08 1:T 2:T 3:T 4:T 5:T 6:T 7:F  8:T ...

스크립트는 정상적으로 실행되지만 입력 파일의 길이가 그리 길지 않은 경우 완료하는 데 약 18초가 걸릴 수 있습니다. 동일한 입력 파일에서 sed를 실행하면 거의 즉시 찾아서 적용해야 할 변경 사항의 긴 목록이 포함됩니다. 왜 이렇게 오래 걸리는지 모르겠습니다. 이것은 각 비트의 이름을 포함하는 내가 만든 txt 파일을 참조하므로 매번 불필요한 읽기를 너무 많이 수행하는 것인지 궁금합니다. 한 번만 로드해도 될까요?

이것은 내 스크립트입니다.

#!/bin/bash

#Variables
d=$(date +%Y-%m-%d_%H. -d '1 hour ago')

# Function to read label files and store labels in arrays
read_label_files() {
    local station_id="$1"
    local io_type="$2"
    local card_number="$3"

    local label_file="s${station_id:3}${io_type}${card_number}.txt"
    local label_array=()

    if [ -f "$label_file" ]; then
        IFS=',' read -ra label_array < "$label_file"
    fi

    echo "${label_array[@]}"
}

# Function to add extracted string into an array
data_string_array=()

for ((i=0; i<${#data_string}; i++)); do
    data_string_array[i]="${data_string:i:1}"
done


# Function to convert input values to T or F
convert_input_values() {
    local data_string="$1"

    local output_string=""

    for (( i=0; i<${#data_string}; i++ )); do
        if [ "${data_string:$i:1}" == "1" ]; then
            output_string+="T "
        else
            output_string+="F "
        fi
    done

    echo "$output_string"
}

# Function to convert output values to T or F
convert_output_values() {
    local data_string="$1"

    local output_string=""

    for (( i=0; i<${#data_string}; i++ )); do
        if [ "${data_string:$i:1}" == "+" ]; then
            output_string+="T "
        else
            output_string+="F "
        fi
    done

    echo "$output_string"
}

# Initialize arrays for inputs and outputs
declare -A input_changes
declare -A output_changes

# Process the input file
while read -r line; do
    timestamp=$(echo "$line" | awk '{print $1}')
    station_id=$(echo "$line" | awk '{print $2}')
    io_type=$(echo "$line" | awk '{print $6}')
    card_number=$(echo "$line" | awk '{print $7}')
    logdate=$(echo "$line" | awk '{print $4}')

    # Remove spaces from the data string
    data_string=$(echo "$line" | awk '{$1=$2=$3=$4=$5=$6=$7=""; print $0}' | tr -d ' ')

    if [ "$io_type" = "In" ]; then
        # Read input label file and store labels in an array
        input_labels=($(read_label_files "$station_id" "i" "$card_number"))

        # Convert input values to T or F
        converted_values=($(convert_input_values "$data_string"))

        # Store current values for comparison
        current_values="${input_changes[$station_id,$card_number]}"
        input_changes[$station_id,$card_number]="$data_string"

        # Print the output line with labels and T/F values
        output_line="$timestamp $station_id $logdate I/O In  $card_number -"
        if [ -z "$current_values" ]; then
#       echo "NEW"
            for ((i=0; i<${#input_labels[@]}; i++)); do
                output_line+=" ${input_labels[i]}:${converted_values[i]}"
            done
        else
#       echo "UPDATE"
            for ((i=0; i<${#current_values}; i++)); do
            current_array[i]="${current_values:i:1}"
            done
            #current_array=($current_values)
            for ((i=0; i<${#data_string}; i++)); do
            data_string_array[i]="${data_string:i:1}"
            done
#echo "old ${current_array[@]}"
#echo "new ${data_string_array[@]}"

            for ((i=0; i<${#input_labels[@]}; i++)); do
#echo "Comparing index $i: data_string_array[${i}] = ${data_string_array[i]}, current_array[${i}] = ${current_array[i]}"
            if [ "${data_string_array[i]}" != "${current_array[i]}" ]; then
                output_line+=" ${input_labels[i]}:${converted_values[i]}"
            fi
            done

#echo "Output Line: $output_line"

        fi
        echo "$output_line" >> /home/logs/IO.$d.txt

    elif [ "$io_type" = "Out" ]; then
        # Read output label file and store labels in an array
        output_labels=($(read_label_files "$station_id" "o" "$card_number"))

        # Convert output values to T or F
        converted_values=($(convert_output_values "$data_string"))

        # Store current values for comparison
        current_values="${output_changes[$station_id,$card_number]}"
        output_changes[$station_id,$card_number]="$data_string"

        # Print the output line with labels and T/F values
        output_line="$timestamp $station_id $logdate I/O Out $card_number -"
        if [ -z "$current_values" ]; then
#       echo NEW
            for ((i=0; i<${#output_labels[@]}; i++)); do
                output_line+=" ${output_labels[i]}:${converted_values[i]}"
            done
        else
#       echo UPDATE
            for ((i=0; i<${#current_values}; i++)); do
            current_array[i]="${current_values:i:1}"
            done
            #current_array=($current_values)
            for ((i=0; i<${#data_string}; i++)); do
            data_string_array[i]="${data_string:i:1}"
            done
#echo "old ${current_array[@]}"
#echo "new ${data_string_array[@]}"
            for ((i=0; i<${#output_labels[@]}; i++)); do
#echo "Comparing index $i: data_string_array[${i}] = ${data_string_array[i]}, current_array[${i}] = ${current_array[i]}"
            if [ "${data_string_array[i]}" != "${current_array[i]}" ]; then
                    output_line+=" ${output_labels[i]}:${converted_values[i]}"
                fi
            done
        fi
        echo "$output_line" >> /home/logs/IO.$d.txt
    fi
done < /home/logs/DataLog.$d.txt

답변1

대답은 이런 종류의 일에는 bash를 사용하지 않는 것입니다. 이를 위해 Python을 배우겠습니다.

관련 정보