Começarei dizendo que acho que esse problema é um pouco menos inocente do que parece.
O que eu preciso fazer: verifique se há uma pasta na variável de ambiente PATH. Pode ser no começo ou em algum lugar depois. Eu só preciso verificar se essa pasta está lá.
Exemplo do meu problema - vamos usar /opt/gnome
.
CENÁRIO 1: a pasta não está no início do CAMINHO
# echo "$PATH"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
# echo "$PATH" | grep ":/opt/gnome"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
Observe que o grep precisa ser específico o suficiente para não ser capturado /var/opt/gnome
. Daí o cólon.
CENÁRIO 2: a pasta está no início do CAMINHO.
# echo "$PATH"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
# echo "$PATH" | grep "^/opt/gnome"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
Esse é o meu problema - preciso procurar dois pontos ou um início de linha com esta pasta. O que eu gostaria de fazer é uma dessas duas expressões de colchetes:
# echo $PATH | grep "[^:]/opt/gnome"
# echo $PATH | grep "[:^]/opt/gnome"
MAS [^
e [:
têm seus próprios significados. Portanto, os dois comandos acima não funcionam.
Existe uma maneira que eu possa grep para esses dois cenários em um comando?
fonte
/opt/gnome:
ou/opt/gnome$
, você vai encontrar/opt/gnome-foo
ou/opt/gnome/bar
.grep '^\(any number of other matches:*:\)*my match\(:.*\)*$'
Respostas:
Se você estiver verificando o conteúdo da
PATH
variável de ambiente, em vez de procurar algo em um arquivo,grep
é a ferramenta errada. É mais fácil (e mais rápido e sem dúvida mais legível) fazê-lo no shell.No bash, ksh e zsh:
Portably:
Observe o uso de em
:$PATH:
vez de$PATH
; dessa maneira, o componente está sempre cercado por dois pontos na string de pesquisa, mesmo que estivesse no início ou no final de$PATH
.Se você estiver pesquisando em uma linha de um arquivo, poderá usar o regexp estendido (por exemplo, exigindo
grep -E
)(^|:)/opt/gnome($|:)
para corresponder,/opt/gnome
mas apenas se for no início de uma linha ou após dois pontos, e somente se estiver no final de a linha ou seguido por dois pontos.fonte
Você pode usar expressões regulares estendidas usando apenas o
grep -E
Você deve corresponder ao início e ao final do caminho que está tentando encontrar se quiser evitar falsos positivos.
Corresponde à instância no início:
Também corresponde à instância no meio:
Evitando falsos positivos:
Não há correspondências lá.
Compacto e elegante. Testado no Debian 7.
fonte
egrep
é o uso obsoletogrep -E
(fonte:man grep
)-w
opção tem alguns problemas. Somente dígitos, letras e sublinhado são considerados "palavras". Portanto, alguns caracteres incomuns, mas possíveis, farão com que falhe. Exemploecho '/sbin:/usr/sbin:/var-/opt/gnome' | grep -w "/opt/gnome"
eecho '/sbin:/usr/sbin:/var./opt/gnome' | grep -w "/opt/gnome"
. Aqueles entregam resultados errados./opt/gnome/somethingelse
.echo "/home/bob/opt/gnome:/opt/gnome/somethingelse:/opt/gnome-beta" | grep -E "(:|^)/opt/gnome(:|$)"
. Editando resposta.Se você não estiver casado
grep
, poderá usarawk
e separar os registros em:
fonte
Você também pode usar
echo "$PATH" | tr ':' '\n' | grep -x "/opt/gnome"
que divide a variável de caminho em linhas separadas (uma por caminho), para
grep -x
procurar resultados exatos. Obviamente, isso tem a desvantagem de que ele precisa de um processo adicionaltr
. E não funcionará quando o nome de uma pastaPATH
contiver caracteres de nova linha.fonte
Eu não sei, é suficiente para responder, mas
irá satisfazer a sua necessidade.
mas
fonte
/
não faz parte da palavra, masr
é./opt/gnome-beta
,/home/bob/opt/gnome
, ...grep -w /usr/local -o <<< /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
------/usr/local /usr/local /usr/local
Para selecionar
/opt/gnome
cercado por caracteres não-palavra (novas linhas,:
,/
, etc) tente este:fonte
Você pode fazer isso de forma confiável e com pouco esforço
grep
. Você pode tirar proveito das extensões amplamente disponíveis e dentre as quais muitas soluções já foram oferecidas, mas mesmo com o regex básico isso é feito com facilidade, embora possa não ser intuitivo à primeira vista.Com regex básico - e assim por diante
grep
- você sempre tem duas âncoras confiáveis - a cabeça e a cauda da linha. Você pode ancorar uma correspondência para ambos, independentemente de sua localização na linha, como:grep
corresponderá do início da linha ao número de ocorrências das\(grouped\)
subexpressões necessárias para encontrar o próximo delimitador e, em seguida, a correspondência explícita, e do final da partida até o final da linha da mesma maneira. Se sua correspondência explícita não corresponder explicitamente, ela falhará e não imprimirá nada.E assim você pode fazer, por exemplo:
Veja por si mesmo:
RESULTADO
fonte
você notou um caso extremo ... você pode evitá-lo forçando a aparição de a: no início da linha:
ou se o caminho for exato, adicione também um no final para garantir que seja delimitado:
fonte