Existem várias maneiras de fazer isso corretamente para manipular entradas arbitrárias.
Com o GNU sed
e um sistema que suporta /dev/stdin
:
sed -n "${n}{p;q;}" file2 | sed -e "$m{r/dev/stdin" -e 'd;p;}' file1
ou, um pouco mais curto 1 :
sed $n'!d;q' file2 | sed -e $m'{r /dev/stdin' -e 'd;p;}' file1
Com qualquer sed
e um shell que suporte a substituição do processo
sed '1h;1d;'$((m+1))'x' <(sed ${n}'!d;q' file2) file1
que também pode ser escrito como
sed ${n}'!d;q' file2 | sed '1h;1d;'$((m+1))'x' - file1
Basicamente, uma invocação de sed
extrai a linha n
de file2
, que é então lida pelo outro sed
como primeiro operando: salva no buffer de retenção, apaga e lê o conteúdo dofile1
2º operando, a saber m+1
, trocando buffers quando na linha sed
(da entrada combinada).
Com qualquer -f
que suporte a leitura de um arquivo de script via stdin
de sed
, é possível executar:
sed ${n}'!d;i\
'${m}'c\
s/\/&&/g
q' file2 | sed -f - file1
aqui, o primeiro n
transforma a linha file2
de sed
em um arquivo de script como
${m}c\
line_n_content_here_with_any_backslash_escaped
que é então usado pelo segundo file1
para processar m
(ou seja, substituir linha a\
pelo seguinte texto ... ). Todas as barras invertidas presentes no texto original (juntamente com as novas linhas incorporadas - mas há apenas uma linha) precisam ser ignoradas porque ao usar qualquer i\
, c\
ou sed
para adicionar texto
<backslash> characters in text shall be removed, and the following character shall be treated literally.
Com qualquer s
, você pode usar o sempre popular comando sed
ubstitute certificando-se de que a string seja interpolada em head
de substituição escapa todos os caracteres reservados - neste caso em particular, é apenas uma linha, por exemplo,
line=$(sed ${m}'!d;s|[\/&]|\&|g;q' file2)
então substitua:
sed ${m}'s/.*/'"$line"'/' file1
Com enormes arquivos de entrada, você pode executar:
{ head -n $((m-1)); { head -n $((n-1)) >/dev/null; head -n 1; } <file2; head -n 1 >/dev/null; cat; } <file1
que faz algo assim:
print (m-1) lines from file1
discard (n-1) lines from file2
print n-th line from file2
discard m-th line from file1
print the remaining lines from file1
embora alguns sed
s sejam burros e não sejam compatíveis com os padrões isso não funciona em todas as configurações ... mas onde isso acontece, isso supera awk
, !
e os gostos em termos de velocidade.
1: com alguns shells você pode precisar desativar a expansão do histórico para que $n
funcione ...
também, $m
e %code% realmente não precisam ser citados aqui, já que devem ser inteiros positivos, embora não causem dano