2014-09-28 63 views
1

介绍

我有一个名为data.dat结构如下文件:迭代和有条件删除

1: 67:  1 :s 
    1: 315:  1 :s 
    1: 648:  1 :ns 
    1: 799:  1 :s 
    1: 809:  1 :s 
    1: 997:  1 :ns 
    2: 32:  1 :s 

算法

,我正在寻找的是算法:

  1. 在此文件中生成1和行数之间的随机数。
  2. 如果第四列为“s”,则删除该行。
  3. 否则产生另一个随机数并重复此操作,直到行数达到某个值。

技术概念

虽然技术概念无关的算法,但我试图解释这一问题。数据显示网络的连接表。该算法允许我们在不同的初始条件下运行它,并研究这些网络的一般属性。特别是,由于删除债券的随机性,这些网络之间的任何共同行为都可以被解释为一个基本规律。

更新:另一个很好的理由在每个步骤中,以产生一个随机数是除去每行后,这可能是因为被剩余行的s/ns属性可以改变。

代码

这里是我的代码至今:

#!/bin/bash 
# bash in OSX 

While ((#there is at least 1 s in the fourth column)); do 

    LEN=$(grep -c "." data.dat) # number of lines 
    RAND=$((RANDOM%${LEN}+1)) # generating random number 

    if [[awk -F, "NR==$RAND" 'data.dat' | cut -d ':' -f 4- == "s"]]; then 
     sed '$RANDd' data.txt 
    else 
     #go back and produce another random 
done 
exit 

我尝试用awk -F, "NR==$RAND" 'data.dat' | cut -d ':' -f 4-找到第四列和sed '$RANDd' data.txt删除线。

问题

  1. 我应该如何检查是否有s双在我的档案?
  2. 我不确定if中的条件是否正确。
  3. 此外,我不知道如何强制循环后else回去生成另一个随机数。

谢谢

我真的很感谢你的帮助。

+1

您正在删除以“:s”结尾的每一行。为什么要随机数字和迭代? – Beta 2014-09-28 04:27:55

+0

这听起来可能是技术性的,但这是一个网络,我有兴趣在随机删除债券的渗透和灵活性。 – Mahdi 2014-09-28 04:31:42

+0

@JohnB:我知道最快的方法是删除所有内衬的'''但这只是研究的一部分。和将来一样,我打算在达到特定阈值(没有s)之前研究这些网络。基本上,如果我可以运行这个,我有一个程序可以运行任何最后数量的行。此外,重要的是随机删除行以避免任何偏见的结果。 – Mahdi 2014-09-28 04:44:06

回答

0

就个人而言,我会建议不要在bash中这样做,除非你绝对没有选择。

这里的另一种方式,你能做到这一点在Perl(在功能上非常相似,但Alex's answer简单一点):

use strict; 
use warnings; 

my $filename = shift; 
open my $fh, "<", $filename or die "could not open $filename: $!"; 
chomp (my @lines = <$fh>); 

my $sample = 0; 
my $max_samples = 10; 
while ($sample++ < $max_samples) { 
    my $line_no = int rand @lines; 
    my $line = $lines[$line_no]; 
    if ($line =~ /:s\s*$/) { 
     splice @lines, $line_no, 1; 
    } 
} 

print "$_\n" for @lines; 

用法:perl script.pl data.dat

文件读入到数组@lines。从数组中选取一个随机行,如果它以:s(后跟任意数量的空格)结尾,请将其删除。在最后打印剩余的行。

这是做你想做的,但我应该警告你,依靠任何语言的内置随机数发生器不是一个好的方法来得出统计学意义上的结论。如果您需要高质量的随机数,则应考虑使用模块(如Math::Random::MT::Perl)来生成它们,而不是使用内置的rand

0
#!/usr/bin/env perl 

# usage: $ excise.pl <data.dat> smaller_data.dat 

my $sampleLimit = 10; # sample up to ten lines before printing output 

my $dataRef; 
my $flagRef; 
while (<>) { 
    chomp; 
    push (@{$dataRef}, $_); 
    push (@{$flagRef}, 1); 
} 
my $lineCount = scalar @elems; 
my $sampleIndex = 0; 
while ($sampleIndex < $sampleLimit) { 
    my $sampleLineIndex = int(rand($lineCount)); 
    my @sampleElems = split("\t", $dataRef->[$sampleLineIndex]; 
    if ($sampleElems[3] == "s") { 
     $flagRef->[$sampleLineIndex] = 0; 
    } 
    $sampleIndex++; 
} 
# print data.dat to standard output, minus any sampled lines that had an 's' in them 
foreach my $lineIndex (0..(scalar @{$dataRef} - 1)) { 
    if ($flagRef->[$lineIndex] == 1) { 
     print STDOUT $dataRef->[$lineIndex]."\n"; 
    } 
} 
0
NumLine=$(grep -c "" data.dat) 
while [ ${NumLine} -gt ${TargetLine} ] 
do 
    # echo "Line at start: ${NumLine}" 

    RndLine=$(((${RANDOM} % ${NumLine}) + 1)) 
    RndValue="$(echo "  ${RANDOM}" | sed 's/.*\(.\{6\}\)$/\1/')" 

    sed "${RndLine} { 
      s/^\([^:]*:\)[^:]*\(:.*:ns$\)/\1${RndValue}\2/ 
      t 
      d 
      }" data.dat > /tmp/data.dat 
    mv /tmp/data.dat data.dat 
    NumLine=$(grep -c "" data.dat) 

    #cat data.dat 
    #echo "- Next Iteration -------" 
done 

在AIX上测试(所以不是GNU sed)。在Linux下,使用--posix对于SED选项,你可以就地临时文件重定向+ +举动在这种情况下使用-i

Dont't忘记RANDOM是不是一个真正的随机网络行为,因此研究了基于不乱价值无法反映具体情况下的现实