Questão sed, insira o arquivo antes da última linha


O seguinte método de arquivo de inserção para sed costumava estar trabalhando, mesmo antes da última linha, mas não mais. É um bug no atual sed?

Demonstração da inserção do método de arquivo com sed:

mkdir /tmp/test
printf '%s\n' {1..3} > /tmp/test/f1
printf '%s\n' {one,two,three,four,five,six,seven,eight,nine,ten} > /tmp/test/f2

$ cat /tmp/test/f2 | sed -e "/nine/r /tmp/test/f1" -e //N
one
two
three
four
five
six
seven
eight
1
2
3
nine
ten

$ head -9 /tmp/test/f2 | sed -e "/nine/r /tmp/test/f1" -e //N
one
two
three
four
five
six
seven
eight
nine
1
2
3

$ cat /tmp/test/f2 | sed -e "/ten/r /tmp/test/f1" -e //N
one
two
three
four
five
six
seven
eight
nine
ten
1
2
3

$ sed --version
GNU sed version 4.2.1
... 

Ou seja, o arquivo de inserção antes do método de linha funciona em todos os lugares, exceto na última linha. Ela costumava estar trabalhando antes. É um bug no atual sed?

obrigado


7


origem


Eu tenho me esforçado para alcançá-lo sem sucesso. Eu mudaria para awk ou perl, mas apenas curiosidade, que foi a versão anterior de trabalho? - Birei
Eu não entendo muito bem a mecânica do // N. Mas se você quiser colocar o texto antes da última linha, por que não apenas anexá-lo à linha antes da última? Então, pule o // N então ele sempre será anexado. Agora você quer o texto do arquivo f1 antes da última linha $ echo -e 'one\ntwo\nthree\nfour' | sed -e '/three/r ./f1' - barlop
"porque não basta anexá-lo à linha antes da última?" O problema é que você não pode prever o que a linha antes do último seria, então eu tenho que jogo contra a última linha, em seguida, insira antes. @Birei, não guardei a versão, nem guardei o tempo que testei. Mas eu cavo o acima da minha nota, que estava trabalhando antes. - xpt
@xpt Eu concordo que seria melhor ser mais genérico, mas você está prevendo a última linha porque no seu exemplo você está declarando explicitamente / dez / assim sabendo de antemão que 'dez' foi a última linha. - barlop
Exatamente @barlop. Assim como um arquivo html, você não sabe qual é o seu conteúdo, mas um arquivo html bem formado teria sempre '</body>como a última vez. Apenas um por exemplo - xpt


Respostas:


Desde que você está gnu sed você poderia usar

'e [COMMAND]'
     This command allows one to pipe input from a shell command into
     pattern space.

na la$linha t:

sed '$e cat insert.txt' file

Com ed (substituir ,p com w se você quiser editar no local):

ed -s file<<IN
- r insert.txt
,p
q
IN

ou

ed -s file <<< $'-1 r insert.txt\n,p\nq\n'

Quando ed lê file o endereço atual está definido para o la$linha t. - (ou -1) define o endereço atual para uma linha antes (isto é, $-1) e r lê em insert.txt para depois da linha atual. ,p imprime o conteúdo do buffer de texto (como eu disse, substitua w para salvar as alterações) e q sai do editor.


5



Isso funciona perfeitamente! (Testado com sed '$e cat /tmp/test/f1' /tmp/test/f2 usando os arquivos fornecidos no OP). Obrigado! - xpt


De acordo com o seu comentário você "tem que jogo contra a última linha", então eu consideraria usar o $ (última linha) e i (inserir comando) em sed. Por exemplo:

sed '$ i\INSERT BEFORE LAST LINE' number.txt
1
2
3
4
INSERT BEFORE LAST LINE
5

Apenas certifique-se de que o arquivo não tenha uma linha vazia como a última linha e isso deve funcionar. Observe o espaço entre o cifrão e o i e a barra invertida (\) depois de i. Isto irá inserir o texto após a barra invertida para a última linha sem precisar de um /pattern/ para a última linha.

NOTA: Este comando adicionará apenas uma linha de texto antes da linha final, não um arquivo. Se você deseja inserir o conteúdo de um arquivo antes da última linha.

Se você quiser adicionar um arquivo inteiro (e você não quer se ele está em sed) Eu usaria isso:

    head -n-1 first_file.txt && cat inserted_file.txt && tail -n1 first_file.txt 

Isso deve exibir tudo, exceto a última linha, então cat oo inserted_file.txt e, em seguida, exibir a última linha do first_file.txt.


5



que coloca uma linha antes da última linha, mas ele disse inserir um Arquivo  antes da última linha - barlop
Este método coloca uma linha antes a última linha, mas não insere um arquivo verdadeiro. Eu vou tomar nota disso na minha resposta. obrigado - skamazin
sua 'resposta' pode ser digna como um comentário, mas eu tenho certeza que o op está ciente disso e não responde a pergunta - barlop