usando sed para substituir dois padrões dentro de um padrão maior

2

Usando o sed como eu poderia substituir dois padrões em um padrão maior em uma única linha?

Dada uma única linha de texto, quero encontrar um padrão (vamos chamar isso de padrão externo) e, dentro desse padrão externo, substituir dois padrões internos.

Aqui está um exemplo de uma linha do texto de entrada:

Z:\source\private\main\developer\foo\setenv.sh(25):     export 'FONTCONFIG_PATH'="$WINE_SHARED_SUPPORT/X11/etc/fonts"

No exemplo acima, o padrão externo é /^.*\([[:digit:]]+\):/ , que deve ser igual a Z:\source\private\main\developer\foo\setenv.sh(25): . Os dois padrões internos são /^[A-Za-z]:/ e /\/ .

Outra maneira de expressar minha pergunta é:

Usando o sed Eu sei como fazer substituições de um padrão usando o comando s , mas como limitar o intervalo do comando s para que ele funcione somente na parte da string de entrada até o (25): ?

O resultado final que estou tentando obter é que a linha de texto é transformada em:

/enlistments/source/private/main/developer/foo/setenv.sh(25):     export 'FONTCONFIG_PATH'="$WINE_SHARED_SUPPORT/X11/etc/fonts"
    
por HairOfTheDog 23.01.2011 / 20:54

4 respostas

1

Este comando converte seu exemplo de entrada em seu exemplo de saída:

sed 's|\|/|g;s|^[^/]*|/enlistments|'

Se alguma das suas entradas contiver barras invertidas na parte após a parte /^.*([[:digit:]]+):/ , você terá que dividir e conquistar para evitar que essas últimas barras invertidas sejam substituídas.

sed 'h;s/^.*([[:digit:]]\+)://;x;s/^\(.*([[:digit:]]\+):\).*//;s|\|/|g;s|^[^/]*|/enlistments|;G;s/\n//'

Explicação (as etapas marcadas com um asterisco ( [*] ) se aplicam a ambos os comandos):

  • h - copia a linha para manter espaço
  • s/^.*([[:digit:]]\+):// - exclui a primeira parte da linha do original no espaço padrão
  • x - troca espaço de padrão e armazena espaço
  • s/^\(.*([[:digit:]]\+):\).*// - mantém a primeira parte da linha da cópia (descarte a última parte)
  • s|\|/|g - [ * ] altera todas as barras invertidas para barras (na versão de divisão e conquista, apenas a parte no espaço padrão - a primeira parte da linha - é afetada)
  • s|^[^/]*|/enlistments| - [ * ] altera tudo o que aparece antes da primeira barra em "/ inscritos" - isso pode ser mais seletivo se necessário
  • G - acrescenta uma nova linha e o conteúdo do espaço de espera no final do espaço padrão
  • s/\n// - remove a nova linha interior
por 24.01.2011 / 02:06
0

Existem dois fatos que você acha úteis:

  1. Por padrão, sed somente substituirá a primeira ocorrência de uma string em uma linha. Então, dada a seguinte linha:

    foo foo
    

    O comando sed s/foo/bar/ resultará em:

    bar foo
    
  2. Você pode limitar um comando sed a linhas que correspondam a um padrão específico. Se você quiser executar a substituição acima apenas nas linhas que contêm a string "xyz", use um comando como este:

    sed '/xyz/ s/foo/bar/'
    

Acho que isso deve ajudá-lo a fazer o que quiser.

    
por 23.01.2011 / 21:48
0

Você poderia tentar

sed -r 's/^[A-Z]:\|\/\//g' | sed 's/^/\/enlistments/'

Agora, isso obviamente exige que não haja barras invertidas na parte depois (25): para funcionar. Mas como eu suspeito que este nunca será o caso devido à estrutura do caminho unix, este nunca será o caso.

    
por 10.05.2011 / 13:31
0

Isso pode funcionar para você (GNU sed):

sed 's/([0-9]\+):/&\n/;h;s/\n.*//;y/\/\//;s/[^/]*/\/enlistments/;G;s/\n.*\n//' file
    
por 22.07.2012 / 18:57