Je commencerai par dire que je pense que ce problème est un peu moins innocent qu'il n'y paraît.
Ce que je dois faire: rechercher un dossier dans la variable d'environnement PATH. Cela pourrait être au début ou quelque part après. J'ai juste besoin de vérifier que ce dossier est là.
Exemple de mon problème - utilisons-le /opt/gnome
.
SCÉNARIO 1: le dossier n'est pas au début de PATH
# echo "$PATH"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
# echo "$PATH" | grep ":/opt/gnome"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
Notez que le grep doit être suffisamment spécifique pour ne pas se bloquer /var/opt/gnome
. D'où le colon.
SCENARIO 2: le dossier est au début de PATH.
# echo "$PATH"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
# echo "$PATH" | grep "^/opt/gnome"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
C'est mon problème - je dois rechercher un deux-points ou un début de ligne avec ce dossier. Ce que je voudrais faire, c'est l'une de ces deux expressions entre crochets:
# echo $PATH | grep "[^:]/opt/gnome"
# echo $PATH | grep "[:^]/opt/gnome"
MAIS [^
et [:
ont leurs propres significations. Par conséquent, les deux commandes ci-dessus ne fonctionnent pas.
Existe-t-il un moyen de grep pour ces deux scénarios dans une seule commande?
la source
/opt/gnome:
ou/opt/gnome$
, vous trouverez/opt/gnome-foo
ou/opt/gnome/bar
.grep '^\(any number of other matches:*:\)*my match\(:.*\)*$'
Réponses:
Si vous vérifiez le contenu de la
PATH
variable d'environnement, au lieu de rechercher quelque chose dans un fichier,grep
c'est le mauvais outil. Il est plus facile (et plus rapide et sans doute plus lisible) de le faire dans le shell.En bash, ksh et zsh:
Portablement:
Notez l'utilisation de
:$PATH:
plutôt que$PATH
; de cette façon, le composant est toujours entouré de deux-points dans la chaîne de recherche, même s'il était au début ou à la fin de$PATH
.Si vous recherchez dans une ligne d'un fichier, vous pouvez utiliser l'expression rationnelle étendue (c'est-à-dire nécessitant
grep -E
)(^|:)/opt/gnome($|:)
pour correspondre,/opt/gnome
mais uniquement si elle se trouve soit au début d'une ligne, soit à la suite d'un signe deux-points, et uniquement si elle est soit à la fin de la ligne ou suivie par deux points.la source
Vous pouvez utiliser des expressions régulières étendues en utilisant simplement
grep -E
Vous devez faire correspondre le début et la fin du chemin que vous essayez de trouver si vous voulez éviter les faux positifs.
Correspond à l'instance au début:
Correspond également à l'instance au milieu:
Éviter les faux positifs:
Aucun match là-bas.
Compact et élégant. Testé sur Debian 7.
la source
egrep
est l' utilisation obsolètegrep -E
(source:man grep
)-w
option a quelques problèmes. Seuls les chiffres, les lettres et le trait de soulignement sont considérés comme des "mots". Donc, certains caractères inhabituels mais possibles feront échouer. Exempleecho '/sbin:/usr/sbin:/var-/opt/gnome' | grep -w "/opt/gnome"
etecho '/sbin:/usr/sbin:/var./opt/gnome' | grep -w "/opt/gnome"
. Ceux-ci donnent de mauvais résultats./opt/gnome/somethingelse
.echo "/home/bob/opt/gnome:/opt/gnome/somethingelse:/opt/gnome-beta" | grep -E "(:|^)/opt/gnome(:|$)"
. Modification de la réponse.Si vous n'êtes pas marié
grep
, vous pouvez utiliserawk
et séparer les enregistrements sur:
la source
Vous pouvez également utiliser
echo "$PATH" | tr ':' '\n' | grep -x "/opt/gnome"
qui divise la variable de chemin en lignes distinctes (une par chemin), donc
grep -x
peut rechercher des résultats exacts. Cela présente bien sûr l'inconvénient de nécessiter un processus supplémentairetr
. Et cela ne fonctionnera pas lorsqu'un nom de dossierPATH
contient des caractères de nouvelle ligne.la source
Je ne sais pas si c'est suffisant pour répondre mais
satisfera votre besoin.
mais
la source
/
ne fait pas partie du mot mais l'r
est./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
Pour sélectionner
/opt/gnome
entouré par des caractères non-mot (nouvelles lignes,:
,/
, etc.) essayez celui - ci:la source
Vous pouvez le faire de manière fiable et avec peu d'effort
grep
. Vous pouvez profiter des extensions qui sont largement disponibles et parmi lesquelles de nombreuses solutions ont déjà été proposées, mais même avec des regex de base, cela se fait facilement, même si cela ne l'est pas intuitivement à première vue.Avec regex de base - et donc avec
grep
- vous avez toujours deux ancres fiables - la tête et la queue de la ligne. Vous pouvez ancrer une correspondance à ces deux éléments indépendamment de son emplacement sur la ligne, comme:grep
correspondra de la tête de la ligne autant d'occurrences des\(grouped\)
sous - expressions qu'il le faut pour rencontrer ensuite votre délimiteur puis votre correspondance explicite, et de la queue de votre correspondance à la queue de la ligne de la même manière. Si votre correspondance explicite ne correspond pas explicitement, elle échouera et n'imprimera rien.Et vous pourriez donc faire, par exemple:
Voir par vous-même:
PRODUCTION
la source
vous avez remarqué un cas de bord ... vous pouvez l'éviter en forçant l'apparition d'un: au début de la ligne:
ou si le chemin est exact, ajoutez-en également un à la fin pour vous assurer qu'il est délimité:
la source