Sed para editar cabeçalho com o conteúdo de outro arquivo

3

Estou tentando substituir um cabeçalho existente em um arquivo com base no conteúdo de outro arquivo.

File1 - names.in:

name1
name2
name3
name4
name5

Arquivo2 - Arquivo de dados.tsv:

chr  begin  end  genes  genes genes genes  genes

File2 contém mais linhas, mas quero substituir cada ocorrência da string genes na primeira linha pelas entradas sucessivas de file1 , para que o cabeçalho se torne:

chr  begin  end  name1.Corrected  name2.Corrected  name3.Corrected  name4.Corrected name5.Corrected

Eu tentei o seguinte script:

genenames=$1 
sed -i -e "1s/\tgenes/\t$genenames\.Corrected/g" Datafile.tsv

Mas quando eu corro assim:

./sed.sh names.in 

Eu obtenho a saída como:

chr  begin  end  .in.Corrected  .in.Corrected  .in.Corrected  .in.Corrected  .in.Corrected

Eu posso entender que o script não lê a entrada. Por favor, sugira uma solução adequada.

    
por user3668772 21.09.2015 / 14:45

3 respostas

2

tente

for x in $(<names.in)
do
sed -i -s "s/ genes/ ${x}.Corrected/" Datafile.tsv
done

cat Datafile.tsv

chr  begin  end  name1.Corrected  name2.Corrected name3.Corrected name4.Corrected  name5.Corrected
  • não use o /g flag que será aplicado a todas as ocorrências (você deseja substituir um por um)
  • substitua meu ' ' por '\t'

  • $names.in expandiria para "o valor da variável de nomes" (concatenar para .in), isso provavelmente se expandiria para .in

  • $(< name.in ) lê o nome do arquivo.in, antes da execução do comando e substitui pelo conteúdo do arquivo (fim da linha fica branco)

um shell mais abrangente

cat "$1" | while read x
do
sed -i -s "s/ genes/ ${x}.Corrected/" "$2"
done

chamado como

 myscript.sh names.in  Datafile.tsv
    
por 21.09.2015 / 15:16
2

Se eu entendi corretamente, você precisa ler os nomes de file1 e substituir cada ocorrência da string genes por entradas sucessivas do arquivo1, mas apenas na primeira linha do arquivo2. Nesse caso, você poderia fazer isso (supondo que você nunca tenha uma string com genes como substring, por exemplo, mygenes ):

while read name
do
    sed -i "1s/genes/$name.Corrected/" file2
done < file1

Alternativamente, você também pode simplesmente concatenar o conteúdo do arquivo1 e substituir tudo de uma só vez:

names=$(perl -pe 's/\n/.Corrected /' file1)
sed -i "1s/genes .*/$names/" file2
    
por 21.09.2015 / 15:33
2

Nada bate um loop while read ao processar texto, mas caso você queira processar seu datafile.tsv < em> apenas uma vez :

sed 's|\(.*\)|1s/genes/.Corrected/|' names.in | sed -f - datafile.tsv

O primeiro sed transforma names.in em um script sed :

1s/genes/name1.Corrected/
1s/genes/name2.Corrected/
1s/genes/name3.Corrected/
1s/genes/name4.Corrected/
1s/genes/name5.Corrected/

que é então executado pelo segundo sed .
Se todas as suas colunas genes forem consecutivas (como em sua entrada de amostra), você também poderá executar:

tr \n \t <names.in | \
sed -E 's|\t|.Corrected&|g;s|(.*).$|1s/genes.*genes//|' | \
sed -f - datafile.tsv

que é semelhante ao primeiro, pois o último sed executa o seguinte script sed :

1s/genes.*genes/name1.Corrected name2.Corrected name3.Corrected name4.Corrected name5.Corrected/

Observe que isso não edita seu arquivo no local. Para isso, use sed com -i (se suportado) ou redirecione > da saída para, por exemplo, newfile then mv newfile datafile.tsv

    
por 13.04.2017 / 14:36