Questão Corresponder personagem ou fim de linha com sed


Tentando limpar um PYTHONPATH variável que tem a sintaxe comum:

/a/path:/another/path/:/one/more/path

Eu quero remover todos os caminhos que começam com /mnt. Primeiro tente com sed:

sed 's,/mnt/[^:]\+:,,g' <<< $PYTHONPATH

Remove todas as ocorrências que começam com /mnt/, seguido por um ou mais caracteres, exceto dois-pontos, e o caractere de dois pontos seguinte.

Isso, no entanto, falhará no seguinte exemplo:

PYTHONPATH="/mnt/first/path:/mnt/second/path"

porque o segundo caminho não termina com dois pontos. Eu não poderia dar à luz nada melhor do que executar outra pesquisa com a condição ligeiramente diferente:

sed 's,/mnt/[^:]\+:,,g;s,/mnt/.*$,,g' <<< $PYTHONPATH

Então, agora, depois que todas as ocorrências que terminam com dois pontos forem removidas, outra execução remove todas as ocorrências (na verdade, há no máximo uma) que começam com /mnt/ e termina com o final da string.

Questões:

  1. Para a tarefa, esta é uma solução aceitável?
  2. Existe um caso especial em que a solução acima irá falhar?
  3. Uma solução de pesquisa única é possível aqui? Apenas curioso

Desde já, obrigado!


1


origem




Respostas:


Como apontado pelos Argonauts, você pode fazer isso em uma linha com a instrução OR. Você não precisa necessariamente usar o -r opção, mas o sed O comando será um pouco mais complexo, já que você tem que escapar dos parênteses e barrar da seguinte forma:

sed 's,/mnt/[^:]\+\(:\|$\),,g' <<< "$PYTHONPATH"

Note que é uma boa prática citar variáveis ​​no bash.


2



Isso não funcionou para mim no MacOS. Fique por aqui instalando e usando o GNU sed. - Phlippie Bosman


O que você tem é aceitável, mas uma saída ainda mais fácil e mais preguiçosa é:

Basta fazer uma nova variável

NEWVAR="${PYTHONPATH}:"
sed 's,/mnt/[^:]\+:,,g' <<< $NEWVAR

Supondo que você esteja atribuindo isso a uma variável e queira que os dois-pontos sejam aparados novamente, com a manipulação da variável bash, você pode fazer isso:

newvar="${PYTHONPATH}:"
nomnt=$( sed 's,/mnt/[^:]\+:,,g' <<< $newvar )
nomnt=${nomnt%%:}
echo ${nomnt}

Ou em todos os sed:

sed 's,/mnt/[^:]\+:,,g;s/:$//;' <<< "${PYTHONPATH}:"

1





Você pode usar expressões regulares estendidas com sed para simplificar um pouco as coisas:

sed -r 's,/mnt/[^:]+(:|$),,g' <<< $PYTHONPATH

o -r indica o uso de um regex estendido, que neste caso é a instrução OR (:|$), fazendo com que ele termine a correspondência de padrão em dois pontos ou no final da linha.

Nota: com as versões OS X e BSD do uso sed -E ao invés de -r

E embora seja provavelmente óbvio, se você está tentando atualizar o próprio PYTHONPATH você precisa atribuir o valor depois de remover as entradas / mnt / *:

export PYTHONPATH=$(sed -r 's,/mnt/[^:]+(:|$),,g' <<< $PYTHONPATH)

1