【发布时间】:2022-08-18 15:11:01
【问题描述】:
如何通过使用 shell 脚本或 awk 对相同的行进行分组来拆分文件?
例如,我有 1 个文件,其内容如下:
1,1,1,1
2,2,2,2
3,3,3,3
x,x,x,x
x,x,x,x
x,x,x,x
x,x,x,x
y,y,y,y
y,y,y,y
y,y,y,y
4,4,4,4
5,5,5,5
我想要的是:所有相等的行都是一个组,并且必须在一个单独的文件中,其他不同的行需要在一个拆分文件中,直到特定限制。例如,如果我的特定限制为 10,则必须将原始文件拆分为包含数字的所有行,直到限制为 10(<= 10),如果不同的行数超过限制,则创建另一个拆分文件并很快。
对于包含字母的相等行,我需要它们有自己的单独文件。所以一个文件只用于 x,x,x,x 行,另一个用于 y,y,y,y 行等等。
行的内容只是示例,实际情况是一个 CSV,其中包含我需要按特定列值分组的所有列的不同值(我为此使用 sort 和 uniq),但无论如何我需要拆分这个 csv通过相等的行组和不同的行 <= 使用 shell 脚本或 awk 限制(我看到 awk 提供了更好的性能)。
你有什么主意吗?
我当前的代码是(它保留第一行,因为我正在考虑 csv 有一个标题):
#!/bin/bash
COLUMN=$1
FILE=$2
LIMIT=$3
FILELENGTH=`wc -l < $FILE`
COUNTER=$LIMIT
NUMS=\"\"
SORTED=\"sorted_\"`basename $FILE`
sort -t, -k $COLUMN -n $FILE > $SORTED
while [ $COUNTER -le $FILELENGTH ]; do
NUMS+=`uniq -c $SORTED | awk -v val=$COUNTER \'($1+prev)<=val {prev+=$1} END{print prev}\'`
NUMS+=\" \"
((COUNTER+=LIMIT))
echo $NUMS \"|\" $COUNTER \"|\" $FILELENGTH \"|\" $SORTED
done
awk -v nums=\"$NUMS\" -v fname=`basename $2` -v dname=`dirname $2` \'
NR==1 { header=$0; next}
(NR-1)==1 {
c=split(nums,b)
for(i=1; i<=c; i++) a[b[i]]
j=1; out = dname\"/\" \"splited\" j \"_\"fname
print header > out
system(\"touch \"out\".fin\")
}
{ print > out }
NR in a {
close(out)
out = dname \"/\" \"splited\" ++j \"_\"fname
print header > out
system(\"touch \"out\".fin\")
}\' $SORTED
-
如果您的真实数据中没有全部为
.s 的行,则不要在示例数据中放置此类行 (.......)。只需给我们一个minimal reproducible example,其中包含简洁、可测试的样本输入和预期输出,我们可以复制/粘贴以进行测试(无需编辑出一堆无用的.......行),以便我们为您提供帮助。 -
您说
I have specific limit as 10,但我们不想看到一个包含多个 10+ 行块的冗长示例,只需将其设置为 3,例如,您的问题 - 您可以将 3 更改为 10 或稍后您想要的任何其他内容。 -
正如您使用的bash tag 指示的那样,您应该将脚本复制/粘贴到shellcheck.net 并修复它告诉您的问题。另请阅读correct-bash-and-shell-script-variable-capitalization。