AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 766081
Accepted
69 420 1970
69 420 1970
Asked: 2024-01-04 14:47:01 +0800 CST2024-01-04 14:47:01 +0800 CST 2024-01-04 14:47:01 +0800 CST

Como posso imprimir a sequência mais longa de linhas com números menores que um limite?

  • 772

Estou aprendendo Perl, mas não sei como resolver esse problema.

Eu tenho um .txtarquivo no seguinte formato:

1 16.3346384
2 11.43483
3 1.19819
4 1.1113829
5 1.0953443
6 1.9458343
7 1.345645
8 1.3847385794
9 1.3534344
10 2.1117454
11 1.17465
12 1.4587485

A primeira coluna contém apenas o número da linha, que não interessa aqui, mas está presente no arquivo; os valores na segunda coluna são a parte relevante.

Quero gerar a sequência contígua mais longa de linhas que apresente números menores que 2,00 na segunda coluna. Para o exemplo acima, seriam as linhas 3 a 9 e a saída deveria ser:

1.19819
1.1113829
1.0953443
1.9458343
1.345645
1.3847385794
1.3534344
text-processing
  • 7 7 respostas
  • 370 Views

7 respostas

  • Voted
  1. aviro
    2024-01-04T20:14:24+08:002024-01-04T20:14:24+08:00

    Perl uma linha:

    perl -ne '$n = (split)[1]; if ($n > 2) {if ($i > $max) {$longest=$cur; $cur=""; $max=$i}; $i=0} else {$cur .= $n . "\n"; $i++} END {print $i > $max ? $cur : $longest}' < file.txt
    

    Multilinha para melhor legibilidade:

    perl -ne '
      $n = (split)[1];
      if ($n > 2) {
        if ($i > $max) {
          $longest=$cur;
          $cur="";
          $max=$i;
         }
         $i=0
      } else {
        $cur.= $n . "\n";
        $i++
      } 
      END {
        print $i > $max ? $cur : $longest
      }' < file.txt
    

    Um forro com awk:

    awk '$2 > 2 { if (i > max) {res=cur; cur=""; max=i} i=0} $2 < 2 {cur = cur $2 "\n"; i++} END {if (i > max) res=cur; printf res}' file.txt
    

    Multilinha:

    awk '
      $2 > 2 { 
        if (i > max) {
          res=cur
          cur=""
          max=i
        }
        i=0
      } 
      $2 < 2 {
        cur = cur $2 "\n"
        i++
      }
      END {
        if (i > max) res=cur
        printf res
      }' file.txt
    
    • 4
  2. Best Answer
    AdminBee
    2024-01-04T19:44:53+08:002024-01-04T19:44:53+08:00

    Esta não é uma tarefa tão trivial. Também há debate se fornecer um programa finalizado é útil para outros aprenderem a resolver um problema em uma linguagem de programação, mas acredito que tem seus méritos, então proponho o seguinte programa (vamos chamá-lo de findlongestsequence.pl:

    #!/usr/bin/perl
    use strict;
    use Getopt::Long;
    
    my $limit; my $infile;
    GetOptions( 'limit=f' => \$limit, 'infile=s' => \$infile );
    
    my $lineno=0; my $groupstart;
    my $currlength=0; my $maxlength=0; my $ingroup=0;
    my @columns; my @groupbuf; my @longestgroup;
    
    if (! open(fileinput, '<', "$infile" )) {exit 1;};
    while (<fileinput>)
    {
        $lineno++;
        @columns = split(/\s+/,$_);
    
        if ( $ingroup == 0 && $columns[1]<$limit )
        {
            $ingroup=1;
            $groupstart=$lineno;
            @groupbuf=();
        }
    
        if ( $ingroup == 1 )
        {
            if ($columns[1]>=$limit )
            {
                $ingroup=0;
                $currlength=$lineno-$groupstart;
        
                if ( $currlength>$maxlength )
                {
                    $maxlength=$currlength;
                    @longestgroup=@groupbuf;
                }
            }
            else
            {
                push(@groupbuf,$columns[1]);
            }
        }
    }
    close(fileinput);
    
    if ( $ingroup == 1 )
    {
        $currlength=$groupstart-$lineno;
        if ( $currlength>$maxlength )
        {
            $maxlength=$currlength;
            @longestgroup=@groupbuf;
        }
    }
    
    print join("\n",@longestgroup),"\n";
    exit 0;
    

    Você pode chamar o programa como

    ./findlongestsequence.pl --infile input.txt --limit 2.0
    

    Isso primeiro interpretará os parâmetros da linha de comando usando Getopt::Long.

    Em seguida, ele abrirá o arquivo e o lerá em linha, mantendo um contador de linha em $lineno. Cada linha será dividida em colunas no espaço em branco.

    • Se o programa não estiver dentro de um grupo de linhas com valores < $limit( $ingroupé zero), mas encontrar uma linha adequada, ele registrará que agora está em tal grupo ( $ingroupdefinido como um), armazenará o início do grupo $groupstarte começará a armazenar em buffer o valores da coluna 2 em uma matriz @groupbuf.
    • Se o programa estiver dentro de tal grupo, mas o valor atual for maior que $limit, ele reconhecerá o final do grupo e calculará seu comprimento. Se for maior que o grupo mais longo registrado anteriormente, o conteúdo ( @groupbuf) e o comprimento ( $currlength) do novo grupo mais longo serão copiados para @longestgroupe $maxlength, respectivamente.

    Como é possível que um grupo seja encerrado no final do arquivo em vez de uma linha com valor > $limit, execute esta verificação também se $ingroupfor verdadeiro no final do arquivo.

    No final, o conteúdo de @longestgroupé impresso \ncomo separador de token.

    • 3
  3. Ed Morton
    2024-01-05T22:53:17+08:002024-01-05T22:53:17+08:00

    Usando qualquer awk:

    $ cat tst.awk
    $2 >= 2 {
        max = getMax(cur,max)
        cur = ""
        next
    }
    { cur = cur $2 ORS }
    END {
        printf "%s", getMax(cur,max)
    }
    function getMax(a,b) {
        return ( gsub(ORS,"&",a) > gsub(ORS,"&",b) ? a : b )
    }
    

    $ awk -f tst.awk file
    1.19819
    1.1113829
    1.0953443
    1.9458343
    1.345645
    1.3847385794
    1.3534344
    
    • 2
  4. Stéphane Chazelas
    2024-01-04T17:42:59+08:002024-01-04T17:42:59+08:00

    Talvez algo como:

    <input perl -snle '
      if ($_ < $limit) {
        $n++;
      } else {
        $max = $n if $n > $max;
        $n = 0;
      }
      END {
        print ($n > $max ? $n : $max);
      }' -- -limit=2 -max=0
    

    Ou se, em vez do número de linhas nesse maior grupo de linhas, você quiser ver essas linhas de acordo com as edições mais recentes da sua pergunta:

    <input perl -snle '
      if ($_ < $limit) {
        push @lines, $_;
      } else {
        @max = @lines if @lines > @max;
        @lines = ();
      }
      END {
        print for @lines > @max ? @lines : @max;
      }' -- -limit=2
    

    Se, como alguém editou na sua pergunta, os números das linhas fazem parte dos dados, adicione a -aopção (modo awk onde os registros são divididos no @Farray) e substitua $_(o registro inteiro) por $F[1](o segundo campo, $F[0]sendo o primeiro).

    • 1
  5. Simon Branch
    2024-01-05T01:20:49+08:002024-01-05T01:20:49+08:00

    Solução idiomática utilizando <>para leitura a entrada e o operador flipflop.

    #!/usr/bin/env perl
    use strict;
    use warnings;
    # https://unix.stackexchange.com/questions/766081/how-to-print-the-longest-sequence-of-lines-featuring-numbers-smaller-than-a-thre
    my $threshold = 2.00;
    my ($section, $maxsection, $len, $maxlen);
    my $flipflop;
    while (<>) {
        # Remove leading line number
        s/^(\d+)\s+//;
        # Flip flop operator
        # https://www.effectiveperlprogramming.com/2010/11/make-exclusive-flip-flop-operators/
        if ($flipflop = $_ <= $threshold .. $_ > $threshold) {
            if ($flipflop =~ /E0$/) {
                # End of section
                if (!defined($maxlen) || $len > $maxlen) {
                    $maxsection = $section;
                    $maxlen = $len;
                }
                $len = 0;
                $section = "";
            } else {
                $len++;
                $section .= $_;
            }
        }
    }
    # One last possible end of section
    if ($flipflop && $len > $maxlen) {
        $maxsection = $section;
    }
    print $maxsection;
    
    • 1
  6. jubilatious1
    2024-01-05T18:27:11+08:002024-01-05T18:27:11+08:00

    Usando Raku (anteriormente conhecido como Perl_6)

    ~$ raku -ne 'BEGIN my (@max,@tmp);  $_ .= words;  \
                 if .[1]  < 2 { @tmp.push: .[1] };    \
                 if .[1] !< 2 { @max = @tmp if @tmp.elems > @max.elems; @tmp = Empty };  \
                 END @max.elems >= @tmp.elems ?? (.put for @max) !! (.put for @tmp);'  file
    

    OU:

    ~$ raku -ne 'BEGIN my (@max,@tmp);  $_ .= words;  \
                 when .[1]  < 2 { @tmp.push: .[1] };  \
                 default { @max = @tmp if @tmp.elems > @max.elems; @tmp = Empty };  \
                 END @max.elems >= @tmp.elems ?? (.put for @max) !! (.put for @tmp);'  file
    

    Aqui estão as respostas escritas em Raku, um membro da família Perl de linguagens de programação. Raku apresenta números racionais , caso você precise manter a precisão ao realizar operações matemáticas simples (por exemplo say 0.1 + 0.2 - 0.3;).

    • A primeira resposta lê linhas $_usando -nesinalizadores linewise sem impressão automática. Tanto a @maxquanto @tmparray são declarados. A linha é quebrada em espaços em branco wordse .=salva novamente em $_. Se ( ifinstrução) a .[1]segunda coluna satisfizer os critérios, os valores serão pushinseridos na @tmpmatriz. Caso contrário, o @tmparray substitui o @maxarray se tiver mais elems(elementos). Independentemente disso, a @tmpmatriz está Empty(esvaziada). Para ENDgarantir que uma sequência contígua final seja/não a mais longa, o operador ternário Test ?? True !! False de Raku é usado para determinar puta matriz mais longa.

    • A segunda resposta é semelhante à primeira, exceto que whensão usadas declarações. No Raku, uma vez whensatisfeita uma condicional, seu bloco associado é executado e o controle reverte para o bloco externo, ignorando quaisquer instruções whenor subsequentes default. Veja a referência abaixo.

    Entrada de amostra:

    1 16.3346384
    2 11.43483
    3 1.19819
    4 1.1113829
    5 1.0953443
    6 1.9458343
    7 1.345645
    8 1.3847385794
    9 1.3534344
    10 2.1117454
    11 1.17465
    12 1.4587485
    

    Saída de amostra:

    1.19819
    1.1113829
    1.0953443
    1.9458343
    1.345645
    1.3847385794
    1.3534344
    

    NOTA: O código acima produzirá a primeira sequência contígua mais longa no caso de empate.

    https://docs.raku.org/syntax/when
    https://docs.raku.org/
    https://raku.org

    • 1
  7. Jas
    2024-01-04T18:05:54+08:002024-01-04T18:05:54+08:00

    Se você não quiser engenharia excessiva, tente esta linha de comando de linha única:

    awk '{print $2}' yourfile.txt | sort -g > youroutput.txt
    
    1. O primeiro comando escolherá a segunda coluna do seu arquivo
    2. O segundo comando classificará a coluna selecionada com base na classificação numérica geral e gravará no arquivo de saída. Para mais detalhes e ajustes, verifique as páginas de manual de awke sort.
    • -1

relate perguntas

  • Grep para um conjunto de linhas de $START a $END AND que contém uma correspondência em $MIDDLE

  • Reorganize as letras e compare duas palavras

  • Subtraindo a mesma coluna entre duas linhas no awk

  • Embaralhamento de arquivo de várias linhas

  • como posso alterar o caso do caractere (de baixo para cima e vice-versa)? ao mesmo tempo [duplicado]

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve