ext a substituição da string por correspondência exata contendo /

4

Estou tentando usar sed para procurar a ocorrência de uma string exata que contenha / nela. Abaixo está a abordagem que estou tentando, mas sem sorte.

input_string="/path /path1 /path2"
search_string="/path"
input_string=echo $input_string | sed "s#\b$search_string\b##g"

Mas quando executo essa sequência de comandos, ainda sou input_string para conter o valor "/ path / path1 / path2" em vez de "/ path1 / path2"

Eu até tentei input_string=echo $input_string | sed "s#\<$search_string\>##g" , mas sem sorte

Estou usando o RHEL6.5 e executando este comando a partir do shell.

    
por greenhorntechie 30.12.2016 / 15:11

3 respostas

4

O problema aqui é o / no padrão em $search_string .

Como / não é um caractere alfanumérico, não é considerado uma "palavra". Isso significa que o padrão \</path\> não corresponderia a /path , pois não há limite de palavras antes do / .

Altere a string de pesquisa para /path\> (ou seja, s##$search_string\>##g ), ou use /path[^0-9] ou, com esses dados de entrada e string de pesquisa específicos, você pode simplesmente usar s#$search_string ##g como substituição.

    
por 30.12.2016 / 16:07
3

resposta curta

use este comando para conseguir o que deseja:

input_string=$(echo $input_string | sed "s#$search_string\b##g")

Resposta longa

Por que sed não está substituindo

\b significa um limite de palavra, e aqui está sua definição:

The metacharacter \b is an anchor like the caret and the dollar sign. It matches at a position that is called a "word boundary". This match is zero-length.

There are three different positions that qualify as word boundaries:

  • Before the first character in the string, if the first character is a word character.
  • After the last character in the string, if the last character is a word character.
  • Between two characters in the string, where one is a word character and the other is not a word character.

Encontrou aqui . Portanto, o primeiro caractere de seu search_string é um / e parece que sed não pode encontrar um limite de palavra devido à primeira regra (porque o / não é um caractere de palavra). / p>

Por que o resultado não é armazenado em input_string

primeiro, você precisa executar os dois comandos ( echo e sed ) e, em seguida, armazenar o resultado na variável input_string . Para fazer isso, coloque os dois comandos dentro de $() . Isso fará com que eles executem e retornem o resultado para sua variável (veja o comando na resposta curta ).

Eu sei que não é uma resposta completa, mas é tudo o que tenho.

    
por 30.12.2016 / 16:40
0

A correspondência exata de palavras em sed é complicada, especialmente se você quiser escrever uma solução portátil ou se a sua definição de "palavra" contiver caracteres especiais diferentes de _ (como na sua situação). A melhor maneira que encontrei para fazer isso é considerar todos os 4 casos em que uma palavra pode aparecer em uma linha de entrada:

  1. No começo
  2. No final
  3. No começo e no final (ocupando toda a linha)
  4. No meio, em algum lugar

Se a sua definição de palavra for simplesmente uma sequência de caracteres que não sejam espaços em branco, a solução a seguir deverá funcionar para você (testada):

_s='[ ]' # contains a space and a literal tab character (CTRL-V + TAB) input_string='echo "$input_string" | sed \ -e "s|^$search_string\($_s\)|\1|g" \ -e "s|\($_s\)$search_string$|\1|g" \ -e "s|^$search_string$||g" \ -e "s|\($_s\)$search_string\($_s\)|\1\2|g"'

Observe que escolhi | como o delimitador em vez de # . Isso ocorre porque # pode aparecer em nomes de arquivos (por exemplo, Os arquivos de salvamento automático do Emacs ) enquanto | é reservado, pelo menos no Linux. Observe também que a saída conterá os caracteres do espaço em branco em torno de cada instância de $search_string . Se você preferir omitir o espaço em branco, poderá usá-lo (testado):

_s='[ ]' # contains a space and a literal tab character (CTRL-V + TAB) input_string='echo "$input_string" | sed \ -e "s|^$_s*$search_string$_s\{1,\}||g" \ -e "s|$_s\{1,\}$search_string$_s*$||g" \ -e "s|^$search_string$||g" \ -e "s|\($_s\)$search_string$_s\{1,\}|\1|g"'

Essa última expressão parece um pouco diferente, e por um bom motivo - você não deseja remover o espaço em branco de ambos os lados de $search_string uma vez que você chegou tão longe no processamento da linha de entrada, porque, ao fazer isso, você removeria o espaço em branco entre palavras não correspondidas em ambos os lados de $search_string , o que as transformaria em conjunto.

Notas finais:

  • Você pode conseguir omitir alguns dos modificadores g em as expressões sed , mas não faz mal deixá-las entrar.
  • Provavelmente é desnecessário dizer, mas se o seu $search_string for um caminho, não pode conter nenhum espaço.
por 30.12.2016 / 20:53