Como substituir primeiro n não. de ocorrência de uma string usando sed e / ou awk?

0

Eu recebi um arquivo alphabet , em que a tem várias ocorrências em uma linha.

$ cat alphabet
a b c d e f g 
h i j k a a l
m n a p q r a
s t u v w a x
y z a k l q z

onde

$ cat alphabet | grep -o a | wc -l
7

Agora, como posso substituir apenas as três primeiras ocorrências de a por Z para que meu arquivo seja semelhante ao seguinte

Z b c d e f g 
h i j k Z Z l
m n a p q r a
s t u v w a x
y z a k l q z
    
por Neel 11.12.2015 / 22:46

4 respostas

2
awk '{
    for (i=1; i<=NF; i++) 
        if ($i == "a" && n < 3) {
            n++
            $i = "Z"
        }
    print
}' alphabet

Ou "one-liner" -ed

awk '{for (i=1;i<=NF;i++) if ($i=="a" && n++<3) $i="Z"; print}' alphabet
    
por 12.12.2015 / 00:20
3

Perl para o resgate:

perl -pe '$c++ while $c < 3 && s/a/Z/' alphabet
    
por 11.12.2015 / 22:58
2

Aqui, o caminho sed

sed -E ':a;N;$!ba;s#a#Z#;s#a#Z#;s#a#Z#' alphabet

Como o sed normalmente funciona em linhas, qualquer comando para sed funcionará apenas em uma linha por vez. Para poder substituir apenas as 3 primeiras ocorrências, precisamos primeiro tornar o arquivo inteiro uma única seleção na qual faremos nossas 3 substituições. Caso contrário, faremos 3 substituições em cada linha.

  • :a cria um rótulo
  • N acrescenta a próxima linha ao espaço de padrões
  • $! ignora a última nova linha
  • ba ramifica para rotular a

Agora selecionamos o arquivo inteiro e estaremos atuando nesse espaço em vez de uma linha de cada vez, fazer 3 substituições de "a" com "Z".

O comando acima só funcionará no GNU sed, mais geral, mas com uma versão um pouco mais feia que deve funcionar no modo não-GNU sed:

sed -e ':a' -e 'N' -e '$!ba' -e 's#a#Z#' -e 's#a#Z#' -e 's#a#Z#' alphabet

EDITAR: Como sugerido nos comentários, adicionando a versão que usa o comando g para primeiro substituir todas as ocorrências de 'a' com 'Z' e então substituir todas as ocorrências de 'Z' depois de 3 com 'a' novamente, o que efetivamente leva a substituir apenas o primeiro 3 ocorrências de 'a'. Desta forma, você pode alterar o último número para refletir o número de substituições que você precisa.

sed -e ':a;N;$!ba;s#a#Z#g;s#Z#a#g4' alphabet

    
por 12.12.2015 / 00:49
1

A solução awk que foi publicada assume que todas as ocorrências de a são palavras separadas. Embora isso seja verdade para os dados exemplo , não é especificado como sendo verdadeiro dos dados reais. A seguinte solução awk está mais no espírito da solução perl que foi postada:

awk '{ while (changes < 3  &&  sub("a", "Z") > 0) changes++; print }' alphabet

Isso substitui as ocorrências ( sub stitutes) de a por Z até que o contador changes atinja 3. Claro, para realmente mudar o arquivo, você precisará fazer algo como

awk '{while (c < 3 && sub("a","Z")>0) c++; print}' alphabet > t && cp t alphabet && rm t

em que t é um arquivo temporário.

    
por 12.12.2015 / 07:45

Tags