linux - 难以从 bash 中的循环创建 .txt 文件
问题描述
我有这个数据:
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 文件中放入来自每个 dataX.txt 的每个 FS 的值的总和. 我很难用英语解释我想要什么,所以这里有一个想要的结果示例
输出文件的预期内容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
但它不起作用...
你能告诉我怎么做吗?
解决方案
因为格式似乎很固定,所以您可以使用多个分隔符分隔输入并在 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
您也几乎可以通过IFS='-;/'
在 while read 循环中将 awk 转换为 bash 1:1。
推荐阅读
- php - 如何在 cakephp 3.7 中检查数据库连接是否存在并关闭连接并重新连接到数据库
- git - git clone 时连接中出现未知的 SSL 协议错误
- javascript - 为什么创建空数组 Javascript 在输出中显示 [(...)] 而不是 (...)?
- javascript - 为什么在 Electron 中安装 Babel 失败?我是否需要通天塔?
- sms - 如何摆脱移远 m66 中的 CMS ERROR 2051
- java - sonarQube 扫描错误 - 使列表的字段瞬态或可序列化
- reactjs - 在渲染方法中调用 SFC 函数有什么好处吗?
- java - java with opencv 程序未在命令提示符下运行,包 org.opencv.core 不存在
- javascript - 如何使用动态文件路径要求 json 文件
- wordpress - 如何更改.../wp-admin/...(不仅仅是登录页面)