Como anexar uma string antes e depois de uma linha usando sed

2

Eu tenho linhas que formam uma saída de comando, conforme indicado abaixo.

service:clus1-svr          clus1-node2                      started    [Z]
service:clus1-svr          clus1-node2                      started

Eu quero adicionar uma string antes e depois da linha que indica apenas [Z]. Então o resultado pode vir como:

<font>service:clus1-svr          clus1-node2                      started    [Z]</font>

Alguém por favor pode me ajudar a fazer isso? Sua ajuda muito apreciada.

eu tentei abaixo, mas isso muda toda a linha da saída

sed -i "s/.*/<font color="red">&<\/font>/"
    
por Sam 03.09.2015 / 22:56

3 respostas

2

Você esteve bem perto de sua tentativa; tudo o que você precisava fazer era refinar a execução da substituição apenas para linhas contendo [Z] no final:

sed -i '/\[Z\]$/ s/.*/<font>&<\/font>/' infile

No entanto, aqui está outra awk solution:

awk '$4=="[Z]" {printf("%s%s%s\n", "<font>", $0, "</font>"); next} {print}' infile
  • $4=="[Z]" : padrão; se o quarto campo do registro atualmente processado for [Z] , executa a seguinte ação; caso contrário, pula para o próximo padrão / ação;
  • printf("%s%s%s\n", "<font>", $0, "</font>") : imprime <font> , o registro atualmente processado e </font> como sequências de caracteres seguidas por uma nova linha;
  • next : pula para o próximo registro;
  • print : imprime o registro atualmente processado seguido por uma nova linha;

Exemplo de saída:

user@debian ~ % cat infile
service:clus1-svr          clus1-node2                      started    [Z]
service:clus1-svr          clus1-node2                      started
user@debian ~ % awk '$4=="[Z]" {printf("%s%s%s\n", "<font>", $0, "</font>"); next} {print}' infile
<font>service:clus1-svr          clus1-node2                      started    [Z]</font>
service:clus1-svr          clus1-node2                      started
    
por kos 03.09.2015 / 23:53
4

Você pode usar isto:

sed -n '/\[Z\]$/ s/^/<font>/;/\[Z\]$/ s/$/<\/font>/p' file.txt

Como você vai usá-lo em STDOUT de outro comando, use-o como, por exemplo, :

some command | sed -n '/\[Z\]$/ s/^/<font>/;/\[Z\]$/ s/$/<\/font>/p'

Basicamente tem duas partes:

  • /\[Z\]$/ s/^/<font>/ corresponderá à linha que tiver [Z] , em seguida, adicionará <font> no início da linha em s/^/<font>/

  • /\[Z\]$/ s/$/<\/font>/ corresponderá a [Z] no final da linha e, em seguida, adicionará </font> no final da linha usando /$/<\/font>/ .

Exemplo:

$ cat file.txt 
service:clus1-svr          clus1-node2                      started    [Z]
service:clus1-svr          clus1-node2                      started

$ sed -n '/\[Z\]$/ s/^/<font>/;/\[Z\]$/ s/$/<\/font>/p' file.txt 
<font>service:clus1-svr          clus1-node2                      started    [Z]</font>

Como @glennjackman apontou, você também pode usar uma construção de agrupamento para fazer todas as substituições de uma única correspondência:

$ sed -n '/\[Z\]$/ { s/^/<font>/; s/$/<\/font>/p }' file.txt 
<font>service:clus1-svr          clus1-node2                      started    [Z]</font>

Que tal uma bash solution:

while IFS= read -r line; do [[ $line =~ \[Z\]$ ]] && echo "<font>${line}</font>"; done <file.txt

Você pode usá-lo como:

some command | while IFS= read -r line; do [[ $line =~ \[Z\]$ ]] && echo "<font>${line}</font>"; done

Isso usa a mesma lógica que o sed one. Se a linha terminar com [Z] ( [[ $line =~ \[Z\]$ ]] ), a linha será impressa no formato desejado.

Exemplo:

$ while IFS= read -r line; do [[ $line =~ \[Z\]$ ]] && echo "<font>${line}</font>"; done <file.txt 
<font>service:clus1-svr          clus1-node2                      started    [Z]</font>
    
por heemayl 03.09.2015 / 23:06
1

Awk versão.

Testado com o exemplo do OP colado duas vezes no mesmo arquivo, para que você possa ver, ele edita as duas linhas que têm [Z] e duas que não o contêm

  $ awk ' {if ($0~/\[Z\]/)  print "<font>"$0"</font>";else print}' testfile.txt                                                                   
<font>service:clus1-svr          clus1-node2                      started    [Z]</font>
service:clus1-svr          clus1-node2                      started
<font>service:clus1-svr          clus1-node2                      started    [Z]</font>
service:clus1-svr          clus1-node2                      started

Para enviar as edições para o arquivo, use a seguinte construção:

awk ' {if ($0~/\[Z\]/) print "<font>"$0"</font>";else print}' testfile.txt > /tmp/tmp.txt && cat /tmp/tmp.txt > testfile.txt

    
por Sergiy Kolodyazhnyy 03.09.2015 / 23:49