Macos 迭代和有条件地删除文件中的行 简介

Macos 迭代和有条件地删除文件中的行 简介,macos,bash,random,awk,sed,Macos,Bash,Random,Awk,Sed,我有一个名为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和行数之间的随机数 如果第四列为“s”,则删除该行 否则,生成另一个随

我有一个名为
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和行数之间的随机数
  • 如果第四列为“s”,则删除该行
  • 否则,生成另一个随机数并重复此操作,直到行数达到某个值 技术概念 虽然技术概念与该算法无关,但我试图解释问题。数据显示网络的连接表。该算法允许我们在不同的初始条件下运行它,并研究这些网络的一般特性。特别是,由于删除键的随机性,这些网络之间的任何共同行为都可以解释为一条基本定律

    更新:在每个步骤中产生随机数的另一个很好的原因是,删除每一行后,可能会更改剩余行的
    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':'-f4-
    查找第四列,并通过
    sed'$RAND'data.txt
    删除该行

    问题
  • 如何检查文件中是否存在
    s
  • 我不确定
    if
    中的条件是否正确
  • 另外,我不知道如何强制
    else
    之后的循环返回以生成另一个随机数
  • 谢谢,

    非常感谢您的帮助。

    #/usr/bin/env perl
    
    #!/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";
        }
    }
    
    #用法:$exerce.plsmaller\u data.dat 我的$sampleLimit=10;#打印输出前,最多采样10行 我的$dataRef; 我的$flagRef; 而(){ 咀嚼; 推送(@{$dataRef},$\; push(@{$flagRef},1); } my$lineCount=标量@elems; my$sampleIndex=0; 而($sampleIndex<$sampleLimit){ 我的$sampleLineIndex=int(兰特($lineCount)); my@sampleElems=split(“\t”,$dataRef->[$sampleLineIndex]; 如果($sampleElems[3]=“s”){ $flagRef->[$sampleLineIndex]=0; } $sampleIndex++; } #将data.dat打印到标准输出,减去其中包含“s”的任何采样行 foreach my$lineIndex(0..(标量@{$dataRef}-1)){ 如果($flagRef->[$lineIndex]==1){ 打印STDOUT$dataRef->[$lineIndex]。“\n”; } }
    就我个人而言,我建议不要在bash中这样做,除非你别无选择

    下面是另一种在Perl中实现的方法(在功能上与Perl非常相似,但更简单):

    使用严格;
    使用警告;
    我的$filename=shift;
    打开我的$fh,”
    在AIX上测试(因此不是GNU-sed)。在Linux下,对sed选项使用
    --posix
    ,在这种情况下,您可以使用
    -i
    代替临时文件+重定向+移动


    不要忘记,
    RANDOM
    不是一个真正的随机值,因此基于非随机值的网络行为研究不能反映一个实际情况,而不是一个特定的案例

    您正在删除以“:s”结尾的每一行"。为什么要费心处理随机数和迭代?这听起来可能有点技术性,但这是一个我感兴趣的网络,在随机移除键的情况下,它的渗透性和灵活性。@JohnB:我知道最快的方法是移除所有带有
    s
    的线条,但这只是研究的一部分。今后,我打算研究这些网络达到特定阈值前的ks(无s).基本上,如果我能运行这个,我有一个程序可以运行任何最后数量的
    s
    行。另外,随机删除行以避免任何有偏差的结果也很重要。也许最好用细节更新您的问题,以准确证明网络研究需要
    随机
    。此外,还有许多语法e您的代码中有错误。可能会有帮助。我想知道,您尝试过任何答案吗?
    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;
    
    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