【问题标题】:Difficulty to create .txt file from loop in bash难以从 bash 中的循环创建 .txt 文件
【发布时间】:2020-03-05 13:26:12
【问题描述】:

我有这些数据:

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 的值的总和数据X.txt。我很难用英语解释我想要什么,所以这里有一个想要的结果示例

输出文件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

但它不起作用......

你能告诉我怎么做吗?

【问题讨论】:

  • 你说它不起作用是什么意思?它是否显示错误消息,是否有错误的结果,是否进入无限循环?您能否编辑您的问题以添加更多详细信息?如果显示错误数据,请在您的编辑中包含输出
  • 您可能需要| sort | uniq 而不仅仅是uniq。无论如何,您已经遍历了每个文件。

标签: linux bash loops file


【解决方案1】:

因为格式看起来很固定,所以可以用多个分隔符分隔输入,然后在 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

Tested on 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

您还可以通过在 while read 循环中执行 IFS='-;/' 几乎将 awk 转换为 bash 1:1。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    相关资源
    最近更新 更多