lendo uma lista de linhas de um arquivo que grava a saída para um utilitário

4

Eu tenho um arquivo com uma lista de linhas que quero ler de outro arquivo. Eu quero produzir essas linhas para um utilitário ( grep ) que me permite ler a linha inteira e extrair informações dela. O arquivo com as linhas é assim:

cat input.txt
2088
2089
2095
2096

Por alguma razão, estou preso a isso. Eu sei que sed pode ter um número de linha específico como um argumento, mas não consigo descobrir como colocar isso em uma variável para alimentá-lo.

    
por binswagger 23.07.2014 / 23:30

6 respostas

1

Se eu entendi o problema corretamente, algo assim deve funcionar:

for i in $(cat numbers.txt); do cat lines.txt|tail -n +$i|head -n 1; done

Para cada um dos números no arquivo "numbers.txt", ele extrai a linha correspondente do outro arquivo e o imprime.

A mesma coisa com sed e xargs é assim:

xargs -i sed "{}q;d" lines.txt <numbers.txt
    
por 23.07.2014 / 23:56
1

Assumindo a interpretação do michas está correta, aqui está uma awk solution:

awk 'FNR==NR{a[i++]=$0} # Process the first file
     FNR!=NR{           # Process the second file
         for (i in a){
             if(FNR==a[i]){
                 print $0
             }
         }
     }' file_with_line_numbers other_file

Em Perl:

perl -E '
    while(<>){
        chomp;
        if($file2) { say if exists $lines{$.} }
        else       { $lines{$_}++             }
    }   continue   { if (eof){$.=0; $file2++} }'\
    file_with_line_numbers other_file
    
por 24.07.2014 / 00:32
1
awk 'NR==FNR{linesToPrint[$0];next}
     FNR in linesToPrint' line-numbers.txt file.txt
    
por 26.07.2014 / 14:18
0

Combine sed com xargs e printf :

sed -n $(xargs printf "%sp;" < input.txt) data

-n indica sed para não imprimir linhas, a menos que você diga explicitamente . xargs executa um comando com as linhas da entrada padrão como seus argumentos. printf formatará cada argumento conforme descrito. O $(...) acima expande para (para o seu arquivo de amostra):

2088p;2089p;2095p;2096p;

, que é uma sequência de comandos sed , dizendo para as linhas de impressão 2088, 2089, 2095 e 2096.

Dessa forma, você lê cada arquivo uma vez, em vez de várias vezes para xargs -i sed "{}q" ou canalizado em head e tail .

    
por 24.07.2014 / 01:46
0

Outra solução perl :

$ perl -MList::Util=any -nle '
    BEGIN {
        open $fh, "<", "input.txt";
        @lines = <$fh>;
        close $fh;
    }
    print if any { $_ == $. } @lines;
' file
    
por 24.07.2014 / 03:58
0
sed '/[^0-9]/d;s/.$/&p/' <input.txt |
sed -nf - file

Isso é dois sed s trabalhando juntos. O primeiro faz uma pequena tentativa de garantir que ele apenas edite linhas apropriadas, recusando-se a imprimir qualquer linha que contenha um único caractere não numérico e apenas editando quaisquer linhas contendo pelo menos um caractere. Basicamente, seu trabalho, no entanto, é transformar sua lista de números de linha em:

2088p
2089p
2095p
2096p

O segundo lê seu script de comando a partir da entrada padrão e não imprime linhas por padrão, então todas essas linhas editadas por sed se tornam uma lista de comandos para o sed o segundo. Ele executa esses comandos em file .

Aparentemente, uma técnica semelhante já foi recomendada, mas existe uma diferença fundamental entre os argumentos de invocação e a entrada de um processo. Existem limites distintos nas listas de discussão como:

some_process $(seq a billion)

Esse tipo de coisa está fadado ao fracasso, mas, desde que o processo saiba como lidar com isso, sua entrada é teoricamente ilimitada. Portanto, nesse caso, sed lê um arquivo - o |pipe - como entrada e o processa como um script sed , o que é muito diferente de entregá-lo a uma cadeia do mesmo comprimento em sua linha de comando na invocação. / p>     

por 30.07.2014 / 10:28