Insira uma linha no número de linha específico com sed ou awk


146

Eu tenho um arquivo de script que preciso modificar com outro script para inserir um texto na 8ª linha.

String para inserir:, Project_Name=sowstestem um arquivo chamado start.

Tentei usar awk e sed, mas meu comando está ficando distorcido.

Respostas:


231
sed -i '8i8 This is Line 8' FILE

insere na linha 8

8 This is Line 8

no arquivo FILE

-i faz a modificação diretamente no arquivo FILE, sem saída para o stdout, conforme mencionado nos comentários de glenn jackman.


3
Sim, a opção -i é específica para o GNU-sed.
usuário desconhecido

1
Não. -I significa "modificar o arquivo especificado no local". A inserção vs. anexar é obtida com '8isomething' vs. '8asomething', independente da opção -i.
usuário desconhecido

11
usuários de mac: com homebrew brew install gnu-sede , em seguida, use-o comgsed
cwd

4
Isso é super útil! Existe alguma maneira para eu inserir espaços no início da linha? Notei sed não está prestando atenção ao espaço em branco inicial ...
elju

9
@elju: Sim, mascará-lo com uma barra invertida: sed '8i\ 8 This is Line 8' FILE.
usuário desconhecido


19

OS X / macOS / FreeBSD sed

A -iflag funciona de maneira diferente no macOS sede no GNU sed.

Aqui está a maneira de usá-lo no macOS / OS X:

sed -i '' '8i\
8 This is Line 8' FILE

Veja man 1 sedpara mais informações.


18

a resposta awk

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new

@ Jackman Jennifer eu preciso entrar #define SERVER@"http://10.35.42.54/ms0.8"para uma linha específica. Como posso conseguir isso?
Nevin Raj Victor

1
Eu acho que Nevin só precisa escapar as aspas em sua string com barras invertidas
Chris Koknat

@waLLe, comece com a página de informações do awk, que possui uma boa descrição de como o awk funciona. Aqui, eu tenho 2 pares "condition {action}", o segundo não tem condição, o que significa que a ação é executada para cada registro. Depois de terminar de ler e ainda tiver dúvidas, entre em contato.
Glenn Jackman

@glennjackman quase lá .. só não consegui isso: arquivo> arquivo.new
w411 3/11

"arquivo" representa o nome do arquivo em que o awk está trabalhando. >é o símbolo de redirecionamento do shell, para que a saída do awk seja armazenada no arquivo chamado "file.new".
Glenn Jackman

16

O POSIX sed(e, por exemplo, OS X sed, sedabaixo) precisa iser seguido por uma barra invertida e uma nova linha. Além disso, pelo menos o OS X sednão inclui uma nova linha após o texto inserido:

$ seq 3|gsed '2i1.5'
1
1.5
2
3
$ seq 3|sed '2i1.5'
sed: 1: "2i1.5": command i expects \ followed by text
$ seq 3|sed $'2i\\\n1.5'
1
1.52
3
$ seq 3|sed $'2i\\\n1.5\n'
1
1.5
2
3

Para substituir uma linha, você pode usar os comandos c(alterar) ou s(substituir) por um endereço numérico:

$ seq 3|sed $'2c\\\n1.5\n'
1
1.5
3
$ seq 3|gsed '2c1.5'
1
1.5
3
$ seq 3|sed '2s/.*/1.5/'
1
1.5
3

Alternativas usando awk:

$ seq 3|awk 'NR==2{print 1.5}1'
1
1.5
2
3
$ seq 3|awk '{print NR==2?1.5:$0}'
1
1.5
3

awkinterpreta barras invertidas em variáveis ​​passadas com -vmas não em variáveis ​​passadas usando ENVIRON:

$ seq 3|awk -v v='a\ba' '{print NR==2?v:$0}'
1
a
3
$ seq 3|v='a\ba' awk '{print NR==2?ENVIRON["v"]:$0}'
1
a\ba
3

Ambos ENVIRONe -vsão definidos pelo POSIX.


7

Soluções Perl:

rapido e sujo:

perl -lpe 'print "Project_Name=sowstest" if $. == 8' file

  • -l retira as novas linhas e as adiciona novamente, eliminando a necessidade de "\ n"
  • -p loops sobre o arquivo de entrada, imprimindo todas as linhas
  • -e executa o código entre aspas simples

$. é o número da linha

equivalente à solução awk de @ glenn, usando argumentos nomeados:

perl -slpe 'print $s if $. == $n' -- -n=8 -s="Project_Name=sowstest" file

  • -s permite um analisador de argumento rudimentar
  • -- impede que -n e -s sejam analisados ​​pelo analisador de argumentos perl padrão

argumentos de comando posicional:

perl -lpe 'BEGIN{$n=shift; $s=shift}; print $s if $. == $n' 8 "Project_Name=sowstest" file

variáveis ​​ambientais:

setenv n 8 ; setenv s "Project_Name=sowstest"
echo $n ; echo $s
perl -slpe 'print $ENV{s} if $. == $ENV{n}' file

ENV é o hash que contém todas as variáveis ​​de ambiente

Getopt para analisar argumentos em hash% o:

perl -MGetopt::Std -lpe 'BEGIN{getopt("ns",\%o)}; print $o{s} if $. == $o{n}' -- -n 8 -s "Project_Name=sowstest" file

Getopt :: Nomes de opção longos e longos

perl -MGetopt::Long -lpe 'BEGIN{GetOptions(\%o,"line=i","string=s")}; print $o{string} if $. == $o{line}' -- --line 8 --string "Project_Name=sowstest" file

Getopt é a solução de biblioteca padrão recomendada.
Isso pode ser um exagero para scripts perl de uma linha, mas pode ser feito


2
Parabéns a você, Chris, por dedicar um tempo para explicar tudo isso e colocá-lo de maneira tão agradável, mas uau, é por isso que eu não gosto de perl.
rsaw

5

Para aqueles que estão no SunOS que não é GNU, o seguinte código ajudará:

sed '1i\^J
line to add' test.dat > tmp.dat
  • ^ J é inserido com ^ V + ^ J
  • Adicione a nova linha após '1i.
  • \ DEVE ser o último caractere da linha.
  • A segunda parte do comando deve estar em uma segunda linha.

5

sed -e '8iProject_Name=sowstest' -i start usando GNU sed

Exemplo de execução:

[root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
[root@node23 ~]# cat a_file
Line #1
Line #2
Line #3
Line #4
Line #5
Line #6
Line #7
Line #8
Line #9
Line #10
[root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
[root@node23 ~]# cat -An a_file 
     1  Line #1$
     2  Line #2$
     3  xxx inserted line xxx$
     4  Line #3$
     5  Line #4$
     6  Line #5$
     7  Line #6$
     8  Line #7$
     9  Line #8$
    10  Line #9$
    11  Line #10$
[root@node23 ~]# 
[root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
[root@node23 ~]# cat -n a_file 
     1  Line #1
     2  Line #2
     3  xxx inserted line xxx
     4  Line #3
     5  xxx (inserted) "line" xxx
     6  Line #4
     7  Line #5
     8  Line #6
     9  Line #7
    10  Line #8
    11  Line #9
    12  Line #10
[root@node23 ~]# 

De onde vem a trilha $na linha 3 após a inserção?
JWW

É da -Abandeira para cat:)
jno 27/10

e se a string que você deseja inserir contiver aspas, parênteses etc.?
Anentropic

Veja atualização para o texto acima. Isso significa que você terá que escapar desses caracteres, conforme apropriado.
jno

0

sed -i "" -e $ '4 a \\ n''Project_Name = sowstest' start

  • Esta linha funciona bem no macOS
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.