Estou tentando usar sed
para imprimir todas as linhas até mas excluindo um padrão específico. Não entendo porque o seguinte não funciona:
sed '/PATTERN/{d;q}' file
De acordo com meu entendimento de script sed, essa expressão deve causar o seguinte:
- Quando uma linha corresponder
/PATTERN/
, execute o grupo que consiste em comandos parad
elete o espaço do padrão (= a linha atual)q
uit depois de imprimir o espaço do padrão atual
Isoladamente, tanto /PATTERN/d
e /PATTERN/q
trabalho; ou seja, d
exclui a linha incorreta e q
faz sed
com que seja encerrada, mas após imprimir a linha , conforme documentado. Mas agrupar as duas operações em um bloco aparentemente faz q
com que seja ignorado.
Eu sei que posso usar Q
em vez de {d;q}
como uma extensão GNU (e isso funciona como esperado!), mas estou interessado em entender por que o acima não funciona e de que maneira estou interpretando mal a documentação.
Meu caso de uso real é (apenas um pouco) mais complexo, já que a primeira linha do arquivo realmente corresponde ao padrão, e estou pulando isso (depois de fazer alguma substituição):
sed -e '1{s/>21/>chr21/; n}' -e '/>/{d;q}' in.fasta >out.fasta
Mas o caso simplificado acima exibe o mesmo comportamento.
Para produzir todas as linhas de um arquivo até a correspondência de um padrão específico (e não produzir essa linha correspondente), você pode usar
Aqui, a saída padrão do espaço padrão no final de cada ciclo é desabilitada com
-n
. Em vez disso, produzimos explicitamente cada linha comp
. Se o padrão fornecido corresponder, interrompemos o processamento comq
.Seu comando real, mais longo, que altera o nome do cromossomo 21 de apenas
21
parachr21
a primeira linha de um arquivo fasta e, em seguida, prossegue para extrair o DNA desse cromossomo até atingir a próxima linha de cabeçalho fasta, pode ser escrito comoou
O problema com sua expressão original é que
d
inicia um novo ciclo (ou seja, força a próxima linha a ser lida no espaço de padrão e há um salto para o início do script). Isso significaq
que nunca seria executado.Observe que para ser sintaticamente correto em sistemas não GNU, seu script original deve se parecer com
/PATTERN/ { d; q; }
. Observe o adicionado;
depoisq
(os espaços não são significativos).d
não apenas exclui o espaço de padrão: da especificação POSIX(minha ênfase)
O
q
comando é inacessível.Você pode obter a mesma saída (apenas as linhas antes da primeira correspondência) usando o formulário de dois endereços:
Mas, diferentemente dos métodos que usam
q
, isso significased
continuar lendo todas as linhas de entrada. Isso pode fazer a diferença em arquivos de entrada grandes ou ao ler de um pipe.