Трудность создать файл .txt из l oop в bash - PullRequest
0 голосов
/ 05 марта 2020

У меня есть эти данные:

cat >data1.txt <<'EOF'
2020-01-27-06-00;/dev/hd1;100;/
2020-01-27-12-00;/dev/hd1;100;/
2020-01-27-18-00;/dev/hd1;100;/
2020-01-27-06-00;/dev/hd2;200;/usr
2020-01-27-12-00;/dev/hd2;200;/usr
2020-01-27-18-00;/dev/hd2;200;/usr
EOF

cat >data2.txt <<'EOF'
2020-02-27-06-00;/dev/hd1;120;/
2020-02-27-12-00;/dev/hd1;120;/
2020-02-27-18-00;/dev/hd1;120;/
2020-02-27-06-00;/dev/hd2;230;/usr
2020-02-27-12-00;/dev/hd2;230;/usr
2020-02-27-18-00;/dev/hd2;230;/usr
EOF

cat >data3.txt <<'EOF'
2020-03-27-06-00;/dev/hd1;130;/
2020-03-27-12-00;/dev/hd1;130;/
2020-03-27-18-00;/dev/hd1;130;/
2020-03-27-06-00;/dev/hd2;240;/usr
2020-03-27-12-00;/dev/hd2;240;/usr
2020-03-27-18-00;/dev/hd2;240;/usr
EOF

Я хотел бы создать файл .txt для каждой файловой системы (например, hd1.txt, hd2.txt, hd3.txt и hd4.txt) и поместить в каждом файле .txt сумма значений каждой FS из каждого dataX.txt. У меня есть некоторые трудности, чтобы объяснить в engli sh, что я хочу, поэтому вот пример требуемого результата

Ожидаемое содержимое для выходного файла hd1.txt:

2020-01;/dev/hd1;300;/
2020-02;/dev/hd1;360;/
2020-03;/dev/hd1;390:/

Ожидается содержимое для файла hd2.txt:

2020-01;/dev/hd2;600;/usr
2020-02;/dev/hd2;690;/usr
2020-03;/dev/hd2;720;/usr

Реализация, которую я сейчас пробовал:

for i in $(cat *.txt | awk -F';' '{print $2}' | cut -d '/' -f3| uniq)
do
    cat *.txt | grep -w $i | awk -F';' -v date="$(cat *.txt | awk -F';' '{print $1}' | cut -d'-' -f-2 | uniq )" '{sum+=$3} END {print date";"$2";"sum}' >> $i

done

Но она не работает ...

Можете ли вы показать мне, как это сделать?

1 Ответ

2 голосов
/ 05 марта 2020

Поскольку формат кажется постоянным, вы можете разделить ввод с помощью нескольких разделителей и легко проанализировать его в awk:

awk -v FS='[;-/]' '
prev != $9 {
    if (length(output)) {
        print output >> fileoutput
    }
    prev = $9
    sum = 0
}
{
    sum += $9
    output = sprintf("%s-%s;/%s/%s;%d;/%s", $1, $2, $7, $8, sum, $11)
    fileoutput = $8 ".txt"
}
END {
    print output >> fileoutput
}
' *.txt

При проверке на repl генерируется:

+ cat hd1.txt
2020-01;/dev/hd1;300;/
2020-02;/dev/hd1;360;/
2020-03;/dev/hd1;390;/
+ cat hd2.txt
2020-01;/dev/hd2;600;/usr
2020-02;/dev/hd2;690;/usr
2020-03;/dev/hd2;720;/usr

В качестве альтернативы вы можете -v FS=';' и использовать split для разделения первого и второго столбцов, чтобы извлечь год и месяц и число hdX.

Если вы ищете bash Решение, я предлагаю вам инвертировать циклы - сначала итерации по файлам, а затем по идентификаторам во втором столбце.

for file in *.txt; do
    prev=
    output=
    while IFS=';' read -r date dev num path; do
        hd=$(basename "$dev")
        if [[ "$hd" != "${prev:-}" ]]; then
            if ((${#output})); then
                printf "%s\n" "$output" >> "$fileoutput"
            fi
            sum=0
            prev="$hd"
        fi
        sum=$((sum + num))
        output=$(
            printf "%s;%s;%d;%s" \
            "$(cut -d'-' -f1-2 <<<"$date")" \
            "$dev" "$sum" "$path"
        )
        fileoutput="${hd}.txt"
    done < "$file"
    printf "%s\n" "$output" >> "$fileoutput"
done

Вы также можете почти перевести awk на bash 1: 1, выполнив IFS='-;/' во время чтения l oop.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...