erro em loop com sed

2

Eu tenho um arquivo que quero analisar:

mmu-miR-15-5p/16-5p/195-5p/424-5p/497-5p    0610007P14Rik
mmu-miR-326-3p/330-5p   0610007P14Rik
mmu-miR-326-3p/330-5p   Lmir
mmu-miR-15/16/195/424/497   0610007P14Rik
mmu-miR-15-5p/16-5p/195-5p/424-5p/497-5p/6838-5p    0610007P14Rik
mmu-miR-15/16/195/424-5p/497    Alinf
mmu-miR-326/330-5p  0610007P14Rik
mmu-miR-326/330 0610007P14Rik
mmu-miR-1/206/613   Crgi
mmu-miR-1-3p/206    0610007P14Rik

a saída desejada:

para a primeira linha

mmu-miR-15-5p   0610007P14Rik
mmu-miR16-5p    0610007P14Rik
mmu-miR195-5p   0610007P14Rik
mmu-miR424-5p   0610007P14Rik
mmu-miR497-5p   0610007P14Rik

e assim por diante ...

Só preciso substituir / por mmu-miR e criar uma nova linha junto com a segunda coluna.

Eu tentei seguir um código de linha no bash:

sed 's/\//\nmmu-miR/g' test.txt

mmu-miR-15-5p
mmu-miR16-5p
mmu-miR195-5p
mmu-miR424-5p
mmu-miR497-5p   0610007P14Rik
mmu-miR-326-3p
mmu-miR330-5p   0610007P14Rik
mmu-miR-326-3p
mmu-miR330-5p   Lmir

Eu tentei usar um loop while e este comando sed:

while read line; do 
    lineCols=( $line ); 
    v1=($(echo "${lineCols[0]}"));
    v2=($(echo "${lineCols[1]}"));
    sed 's/\//\n/g' ${v1};
done <test.txt

mas recebeu um erro:

sed: can't read mmu-miR-15-5p/16-5p/195-5p/424-5p/497-5p: No such file or directory
sed: can't read mmu-miR-326-3p/330-5p: No such file or directory
sed: can't read mmu-miR-326-3p/330-5p: No such file or directory
sed: can't read mmu-miR-15/16/195/424/497: No such file or directory
sed: can't read mmu-miR-15-5p/16-5p/195-5p/424-5p/497-5p/6838-5p: No such file or directory

O que estou fazendo de errado?

    
por Rupesh 14.11.2016 / 18:30

2 respostas

2

Como conseguir isso com awk

Para melhor legibilidade / facilidade de uso, crie um script awk ( myScript.awk ) com o seguinte conteúdo:

{ 
  n=split($1, a, "/")
  split(a[1], b, "-")

  for (i=1; i<n+1; i++) {
    if (i == 1) {
      printf a[i]"\t"$2"\n"
    }
    else {
      printf b[1]"-"b[2]"-"a[i]"\t"$2"\n"
    }    
  }
}

Como funciona:

n=split($1, a, "/")

Esta linha pega o primeiro campo (por exemplo "mmu-miR-15-5p/16-5p/195-5p/424-5p/497-5p" para a primeira linha), divide com separador "/", armazena no array a e armazena o número de elementos divididos em código%. Para a primeira linha:

a[1] = "mmu-miR-15-5p"
a[2] = "16-5p"
a[3] = "195-5p"
a[4] = "424-5p"
a[5] = "497-5p"
n = 5

Lembre-se que n instruções são executadas para cada linha, então o resultado será diferente para a próxima linha!

split(a[1], b, "-")

Da mesma forma, essa linha pega o primeiro elemento de awk e o divide com o separador "-". Isso produz:

b[1] = "mmu"
b[2] = "miR"
b[3] = "15"
b[4] = "5p"

Quando tivermos esses arrays, tudo o que precisamos fazer é percorrer o número de linhas de saída (número de elementos separados "/" em uma linha de entrada) e construir cada linha com bits de arrays a e a ! Temos que fazer uma exceção para a primeira linha porque b já contém "mmu-miR-", portanto, o a[1] para diferenciar esse caso!

Como executá-lo

awk -f myScript.awk input.txt

Testado, ele gera o que você pede em sua pergunta.

NOTA Como declarado no meu comentário sobre a sua pergunta, usar uma única invocação if é muito mais eficiente e "amigável ao shell" do que o loop em todas as linhas do seu arquivo.

EDIT NOTE Eu modifiquei o script após o seu comentário. Deve ficar bem agora!

    
por 14.11.2016 / 19:00
0

Acho que você está procurando algo assim:

cat inputFile.txt | while read line
    do
        eval 'echo "$line" | sed 's|^\([^/]*\)/\([^ ]*\) \(.*\)|name="" ports= tag=""|''
        echo "$name $tag"
        realname='echo "$name" | sed 's|-[0-9].*||''
        for port in $(echo $ports | sed 's|/| |g')
        do
            echo "$realname-$port $tag"
            #or echo "$realname$port $tag", but I suspect a typo in your initial post
        done
    done
    
por 14.11.2016 / 18:34

Tags