linux命令根据模式将大型csv文件随机转换为备用行

时间:2014-09-06 16:08:15

标签: linux csv command-line ubuntu-12.04 shuffle

我有一个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上。

3 个答案:

答案 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 )