Usando sed / awk para alterar palavras entre dois padrões

2

Eu estou escrevendo o script de shell que deve processar através de algum texto, eu tenho o texto assim:

read build { file1 file2 file3 }
check build { file2 file3 file4 }
read build { file4 file5 file6 }

Eu quero adicionar algum texto antes de todos os arquivos - ou seja, palavras, que estão incluídas entre colchetes nas linhas de 'leitura de compilação', o que você acha que é a melhor ideia para conseguir isso? Os resultados devem ser assim:

read build { MY_ADDED_WORDfile1 MY_ADDED_WORDfile2 MY_ADDED_WORDfile3 }
check build { file2 file3 file4 }
read build { MY_ADDED_WORDfile4 MY_ADDED_WORDfile5 MY_ADDED_WORDfile6 }

Eu estava tentando com greping que linhas, em seguida, analisá-lo para matriz e concatenar este "arquivo" strings com a palavra que eu quero adicionar, mas acho que não é uma solução "inteligente". Obrigado pela sua ajuda.

Os arquivos de entrada são assim:

set build { file1 file2 file3 file4 }
check $build

read build -new -f $build
read build -new -f { fileA fileB fileC fileD }

set build {file5 file6 file7 }

read build -old -f $build
read build -old -f { fileX fileZ fileD }

check_that_building

O resultado deve ser assim:

set build { file1 file2 file3 file4 }
check $build

read build -new -f $build
read build -new -f { MY_ADDED_WORDfileA MY_ADDED_WORDfileB MY_ADDED_WORDfileC MY_ADDED_WORDfileD }

set build {file5 file6 file7 }

read build -old -f $build
read build -old -f { MY_ADDED_WORDfileX MY_ADDED_WORDfileZ MY_ADDED_WORDfileD }

check_that_building

Há sempre um espaço antes de abrir o suporte, mas pode ser uma situação em que não haverá espaço após o suporte de abertura; pode haver um espaço antes de fechar o suporte, mas nem sempre é. Casos possíveis:

read build -old -f { fileX fileZ fileD }
read build -old -f {fileX fileZ fileD }
read build -old -f { fileX fileZ fileD}
read build -old -f {fileX fileZ fileD}
    
por TheOmniano 11.11.2015 / 20:09

1 resposta

1

Eu não consegui descobrir imediatamente como fazer isso em sed sem assumir que há pelo menos um caractere que é conhecido nunca aparecer na entrada. Eu assumi que # nunca aparecerá na entrada (ou na sua palavra adicionada). Isso parece funcionar:

sed '/read build/ {
        s/{/{ /
        : fruit
        s/\({.*\) \([^}# ][^ ]*\)/#MY_WORD/
        t fruit
        s/#/ /g
        s/{ /{/
}'

Nas linhas que contêm read build Primeiro, insere um espaço após o { . Em seguida, ele procura por um espaço que está em algum lugar depois de um { e imediatamente antes de uma palavra (presumivelmente um nome de arquivo). Substitui o espaço por # , insere sua palavra, e volta e procura por mais. ( fruit é um rótulo de loop arbitrário.) Depois de encontrá-los, todos os caracteres # retornam aos espaços, e remove o espaço que ele inseriu (após o { ).

Além do bit sobre # não ocorrendo na entrada, isso pressupõe que

  • } é o último caractere não vazio em cada linha read build e
  • espaços em branco são apenas espaços; sem guias.

Em awk :

awk '/read build/ {
        in_braces=0
        for (i = 1; i <= NF; i++) {
                if ($i == "{") in_braces=1
                else if (substr($i,1,1) == "{") {
                        $i = "{MYWORD" substr($i,2)
                        in_braces=1
                }
                else if ($i == "}") in_braces=0
                else if (in_braces) $i = "MY_WORD" $i
        }
      }
      { print }'

Para cada linha read build , Ele percorre todas as palavras (campos) na linha. Ele usa uma variável de estado ( in_braces ) para acompanhar se está entre { e } ; se for, modifica cada palavra para começar com sua palavra adicionada. Observe que ele precisa lidar com dois casos ligeiramente diferentes:

  • se uma palavra for { , defina o sinalizador para começar a modificar todas as palavras subsequentes e
  • se uma palavra começa com { , é na verdade um composto da forma {fileX , então modifique it para ser a concatenação de { , a palavra adicionada e o nome do arquivo fileX . E também defina o sinalizador para modificar todas as palavras subsequentes.

Enquanto isso permite separadores como separadores de palavras, tem a fraqueza que colapsa o espaço em branco em um único espaço. Então, por exemplo, a entrada

read build    {    file1    file2    file3    }

produziria a saída

read build { MY_WORDfile1 MY_WORDfile2 MY_WORDfile3 }

Além disso, isso pressupõe que

  • o { está no início de uma palavra (ou seja, tem espaço em branco antes disso), e
  • ou } é o último caractere não em branco em cada linha read build , ou é uma palavra separada (ou seja, tem espaços em branco antes e depois)

Permite múltiplos conjuntos de chaves; por exemplo,

read build { file1 file2 file3 } text to be left alone { file4 file5 file6 }
    
por 11.11.2015 / 21:24

Tags