Selecione as linhas com exatamente duas colunas no Linux

3

Eu tenho um arquivo que é um mapeamento entre o nome do arquivo e as transcrições correspondentes. O nome do arquivo e as transcrições são separados por um caractere TAB.

A transcrição do arquivo pode conter uma ou mais palavras separadas por um único espaço em branco. A seguir está um layout do arquivo,

[filename] [tab space] [trancription]

Em algumas linhas, a coluna de transcrição está vazia. Essas linhas serão da forma

[filename]

i.e. não há transcrição disponível para esse nome de arquivo.

Agora, meu trabalho é garantir que eu selecione apenas as linhas que tenham nome de arquivo e transcrição (ou seja, os arquivos cuja coluna de transcrição não esteja vazia).

Eu tentei os seguintes comandos

(1) awk 'NF>2' filename

(2) awk 'NF==2' filename

(3) awk 'NF>1' filename

mas não obteve os resultados

Além disso, quando usei o comando

(4) awk ' NF==2 {print $0} '   myfile  > newfile

Eu também estava recebendo essas linhas com apenas uma coluna, ou seja, o campo "filename".

Quando escrevo NF<1 não há saída (conforme esperado) Quando eu escrevo NF<2 novamente, não há saída (estranho, deveria ter exibido linhas com apenas uma coluna) Quando eu escrevo NF ==3 eu estou recebendo as linhas que têm exatamente duas colunas (novamente confuso)

Qual é o truque? É realmente confuso.

Agora estou enviando a amostra de entrada

M07UP36A0821I40.wav 
M07UP36A0821I41.wav 
M07UP36A0821I410.wav    gaajara <bn>
M07UP36A0821I411.wav    tiina sau <pau> taintaaliisa
M07UP36A0821I412.wav    geehuun anya <bn>
M07UP36A0821I413.wav    geehuun daraa <babble>

Agora eu uso o comando

grep '^[^[:blank:]]\+[[:blank:]]\+[^[:blank:]]\+$' cll

Este comando não está dando saída (nem no terminal nem no arquivo redirecionado).

Agora há uma coisa INTERESSANTE a notar:

Quando o arquivo de entrada contém

M07UP36A0822I413.wav    <bn> geehuun daraa <horn> <babble>
M07UP36A0822I414.wav    
M07UP36A0822I415.wav    gudxqa piilaa <horn> <babble>
M07UP36A0822I416.wav    <vn> gudxqa
M07UP36A0822I417.wav    gudxqa
M07UP36A0822I418.wav    gudxqa anya <babble>
M07UP36A0822I419.wav    harii matxara <bn> <babble>

Novamente, usando o mesmo comando

grep '^[^[:blank:]]\+[[:blank:]]\+[^[:blank:]]\+$' foo
O terminal

tem STARTED mostrando a saída. A saída disso foi obtida como

M07UP36A0822I417.wav    gudxqa

Minha saída desejada para o arquivo foo seria aquelas linhas que estão completas (a primeira coluna e a segunda coluna devem estar lá). Aqui está a saída requerida

M07UP36A0822I413.wav    <bn> geehuun daraa <horn> <babble>
M07UP36A0822I415.wav    gudxqa piilaa <horn> <babble>
M07UP36A0822I416.wav    <vn> gudxqa
M07UP36A0822I417.wav    gudxqa
M07UP36A0822I418.wav    gudxqa anya <babble>
M07UP36A0822I419.wav    harii matxara <bn> <babble>

Eu usei o seguinte comando no arquivo cll (o primeiro exemplo na minha pergunta)

awk -F'\t' '(NF !=2) { print "line: " NR " does not have 2 columns: " $0 ;}' cll

O resultado foi exibido no terminal. O resultado é

line: 1 does not have 2 columns: M07UP36A0821I40.wav 
line: 2 does not have 2 columns: M07UP36A0821I41.wav 
line: 3 does not have 2 columns: M07UP36A0821I410.wav    gaajara <bn>
line: 4 does not have 2 columns: M07UP36A0821I411.wav    tiina sau <pau> taintaaliisa
line: 5 does not have 2 columns: M07UP36A0821I412.wav    geehuun anya <bn>
line: 6 does not have 2 columns: M07UP36A0821I413.wav    geehuun daraa <babble>
    
por Upendra Pratap Singh 08.02.2016 / 08:39

3 respostas

4

Usando grep :

grep -E '^[^\s]+\s+[^\s]+$' file.txt
  • [^\s]+ conterá a primeira coluna, depois qualquer número de espaços em branco \s+ , seguido pela segunda (última) coluna

  • ^ indica o início e $ indica o final da linha

POSIX-ly:

grep '^[^[:blank:]]\+[[:blank:]]\+[^[:blank:]]\+$' file.txt
    
por 08.02.2016 / 08:44
0

Outras respostas, usando \s+ estão com correspondência excessiva! \s corresponde a espaços, também, que ocorrem nos dados. O que você está procurando é "Field_not_containing_TAB" seguido por "Tab", seguido por "Field_not_containing_TAB". ou, em fala de regexp,

egrep '^[^ Separador ]+ Separador [^ Separador ]+$' file.txt

Nota: não deve haver nenhum caractere Espaço entre os '' s no meu egrep rexexp. Você os vê lá devido ao meu uso da tag de formatação kbd , que eu tive que usar para tornar Tab visível.

As correspondências regexp (ou com a opção -v para egrep , não correspondem) aos dados fornecidos.

    
por 08.02.2016 / 11:48
0

Para você, 2 colunas é: algo [TAB] alguma coisa, algo pode ter um espaço nela. Então diga ao awk que seu separador de campo é uma guia:

awk -F'\t' '(NF==2)'

para descobrir os outros:

awk -F'\t' '(NF !=2) { print "line: " NR " does not have 2 columns: " $0 ;}'

Editar : você parece "induzir em erro" sobre a estrutura do arquivo: você disse que ele conterá 1 palavra ou 1 palavra, uma TAB e 1 ou várias palavras (separadas por espaços). Se assim for, o acima deveria ter funcionado. No entanto, dado o resultado do comando acima em seu arquivo, acho que é: 1 palavra, [espaços ou tabulações] e talvez palavras [e espaços ou tabulações entre]

Assim, a solução se torna:

awk -F'[\t ]+'  '(NF>=2)'    #words are separated by space&tabs, and we want at least 2 words [a filename, and its description]

uma variante: gera qualquer linha que tenha a segunda palavra não vazia:

awk -F'[\t ]+'  '(length($2)>0)'    #words are separated by space&tabs, and we want athe 2nd word to be non empty
#or, one that also verifies the 1st word is non empty:
awk -F'[\t ]+'  '(length($1)>0 && length($2)>0)'    #1st and 2nd words are non-empty
    
por 08.02.2016 / 10:56

Tags