我有一个40M + csv文件。其中一列是二进制指示符(-1,1)。我想知道是否有一个linux命令来创建一个用-1和1交替行的新文件。
旧:
1,x,y
-1,t,r
-1,e,t
1,r,t
新:
1,x,y
-1,t,r
1,r,t
-1,e,t
Id不必遵循关于-1和1如何被混洗(可以是随机的)的任何特定逻辑,只要它交替每行的一行。 我在Ubuntu 12.04上。
答案 0 :(得分:2)
这是一个shell / awk解决方案。不是最有效的,但考虑到现代机器的速度,不应该是一个问题。
首先,在pos和neg值之间分割数据。
awk '/^-/{print}' minus1Pos1data.txt > negsData.txt
awk '/^[^-]/{print}' minus1Pos1data.txt > posData.txt
现在合并这两个文件,使用awk数组来保存第一个文件。如果你想把neg数作为第一条记录,你可以改变顺序。
awk 'pass==1{pos[FNR]=$0} pass==2{print pos[FNR]; print}' pass=1 posData.txt pass=2 negsData.txt > alternateRows.txt
cat alternateRows.txt
1,x,y
-1,t,r
1,r,t
-1,e,t
awk评估cmd行pass=1
上的变量赋值并测试它们pass==1
? VS pass==2
? (在awk
代码内)并且仅执行pass==?
测试为真的块。请注意,pass=1
是一个赋值语句,而pass==1
是一个相等的测试。
首次传递将第一个文件加载到数组pos
中,并将当前文件的记录号(FNR)作为键。
第二遍使用其当前记录编号(FNR)获取pos
数组rec,裸print
cmd可以是print $0
,这意味着打印当前行(来自pass = 2文件)。
IHTH。
答案 1 :(得分:1)
以下是使用grep,shuf和paste命令的另一种解决方案:
<强> shuffle1-1.sh 强>
#!/usr/bin/env bash
input=$1
if [ $# -eq 0 ]
then
echo "must provide a file as 1st parameter..."
exit -1
fi
# split data between pos and neg values and shuffle them
# in temporary files
grep -v "\-1" $input | shuf > tmp_subset1
grep "\-1" $input | shuf > tmp_subsetm1
# alternate 1 and -1 line
paste -d"\n" tmp_subset1 tmp_subsetm1
# cleanup
rm tmp_subset1
rm tmp_subsetm1
<强>输出强>
# ./shuffle1-1.sh test.data
1,x,y
-1,t,r
1,r,t
-1,e,t
# ./shuffle1-1.sh test.data
1,x,y
-1,e,t
1,r,t
-1,t,r
# cat test.data
1,x,y
-1,t,r
-1,e,t
1,r,t
如果您的文件的行数与1和-1不同,则在末尾添加| grep 1
应该删除空白行:
# ./shuffle1-1.sh test.data2
1,z,z
-1,e,t
1,x,y
-1,t,r
1,r,t
1,Z,Z
# ./shuffle1-1.sh test.data2 | grep 1
1,r,t
-1,t,r
1,x,y
-1,e,t
1,z,z
1,Z,Z
答案 2 :(得分:1)
这是一个单行:
paste -d"\n" <( grep '^1,' test.txt ) <( grep '^-1,' test.txt )