J'essaie d'utiliser sed pour nettoyer les lignes d'URL pour extraire uniquement le domaine.
Donc à partir de:
http://www.suepearson.co.uk/product/174/71/3816/
Je voudrais:
http://www.suepearson.co.uk/
(avec ou sans la barre oblique de fin, cela n'a pas d'importance)
J'ai essayé:
sed 's|\(http:\/\/.*?\/\).*|\1|'
et (échapper au quantificateur non gourmand)
sed 's|\(http:\/\/.*\?\/\).*|\1|'
mais je n'arrive pas à faire fonctionner le quantifier non gourmand ( ?
), donc il finit toujours par correspondre à la chaîne entière.
sed -E 's...
. Pourtant, aucun opérateur réticent.cut -d'/' -f1-3
œuvres simples .Réponses:
Ni regex Posix / GNU de base ni étendu ne reconnaît le quantificateur non gourmand; vous avez besoin d'une expression régulière ultérieure. Heureusement, l'expression rationnelle Perl pour ce contexte est assez facile à obtenir:
la source
-pi -e
.perl
est requis par POSIXsed
utilisant une syntaxe fondamentalement identique à celle dused
Dans ce cas spécifique, vous pouvez faire le travail sans utiliser une expression régulière non gourmande.
Essayez cette expression régulière non gourmande
[^/]*
au lieu de.*?
:la source
([^&=#]+)=([^&#]*)
. Il y a des cas qui ne fonctionnent pas de cette façon, par exemple lors de l'analyse de l'URL de sa partie hôte et du chemin avec la barre oblique finale supposée facultative pour être exclue de la capture:^(http:\/\/.+?)/?$
Avec sed, j'implémente généralement la recherche non gourmande en recherchant autre chose que le séparateur jusqu'au séparateur:
Production:
c'est:
-n
s/<pattern>/<replace>/p
;
séparateur de commande de recherche au lieu de/
pour le rendre plus facile à taper afins;<pattern>;<replace>;p
\(
...\)
, accessible plus tard avec\1
,\2
...http://
[]
,[ab/]
signifierait soita
oub
ou/
^
au[]
moyennot
, donc suivi de quoi que ce soit , mais la chose dans la[]
[^/]
signifie donc tout sauf le/
caractère*
est à répéter groupe précédent si des[^/]*
moyens , à l' exception des caractères/
.sed -n 's;\(http://[^/]*\)
signifie rechercher et mémoriserhttp://
suivi de tous les caractères sauf/
et rappelez-vous ce que vous avez trouvé/
, ajoutez-en un autre/
à la fin:sed -n 's;\(http://[^/]*\)/'
mais nous voulons faire correspondre le reste de la ligne après le domaine, alors ajoutez.*
\1
) est le domaine, alors remplacez la ligne correspondante par des éléments enregistrés dans le groupe\1
et imprimez:sed -n 's;\(http://[^/]*\)/.*;\1;p'
Si vous souhaitez également inclure une barre oblique inverse après le domaine, ajoutez une barre oblique inverse supplémentaire dans le groupe à retenir:
production:
la source
sed ne prend pas en charge l'opérateur "non gourmand".
Vous devez utiliser l'opérateur "[]" pour exclure "/" de la correspondance.
PS il n'y a pas besoin de barre oblique inverse "/".
la source
s/([[:digit:]]\.[[1-9]]*)0*/\1/
ne fonctionnerait évidemment pas bien pour1.20300
. Étant donné que la question d'origine concernait les URL, elles doivent cependant être mentionnées dans la réponse acceptée.Simuler un quantificateur paresseux (non gourmand) dans
sed
Et toutes les autres saveurs regex!
Recherche de la première occurrence d'une expression:
POSIX ERE (en utilisant l'
-r
option)Regex:
Sed:
Exemple (recherche de la première séquence de chiffres) Démo en direct :
Comment ça marche ?
Ce regex bénéficie d'une alternance
|
. À chaque position, le moteur essaie de choisir la correspondance la plus longue (il s'agit d'un standard POSIX qui est également suivi par quelques autres moteurs), ce qui signifie qu'il continue.
jusqu'à ce qu'une correspondance soit trouvée([0-9]+).*
. Mais l'ordre est également important.Puisque l'indicateur global est défini, le moteur essaie de continuer à faire correspondre caractère par caractère jusqu'à la fin de la chaîne d'entrée ou de notre cible. Dès que le premier et le seul groupe de capture du côté gauche de l'alternance est apparié
(EXPRESSION)
reste de la ligne est immédiatement consommé.*
. Nous détenons désormais notre valeur dans le premier groupe de capture.POSIX BRE
Regex:
Sed:
Exemple (recherche de la première séquence de chiffres):
Celui-ci est comme la version ERE mais sans alternance impliquée. C'est tout. À chaque position, le moteur essaie de faire correspondre un chiffre.
Si on le trouve, d' autres chiffres suivants sont consommés et capturés et le reste de la ligne est immédiatement appariées autrement puisque des
*
moyens plus ou zéro , il saute sur le deuxième groupe de capture\(\([0-9]\{1,\}\).*\)*
et arrive à un point.
pour correspondre à un seul caractère et ce processus se poursuit.Recherche de la première occurrence d'un expression délimitée :
Cette approche correspondra à la toute première occurrence d'une chaîne qui est délimitée. Nous pouvons l'appeler un bloc de chaîne.
Chaîne d'entrée:
-EDE:
end
-SDE:
start
Production:
Le premier regex
\(end\).*
correspond et capture le premier délimiteur d'extrémitéend
et les substituants correspondent tous aux caractères capturés récents qui est le délimiteur d'extrémité. A ce stade , notre production est:foobar start block #1 end
.Ensuite, le résultat est transmis à la deuxième expression régulière
\(\(start.*\)*.\)*
qui est identique à la version POSIX BRE ci-dessus. Il correspond à un seul caractère si le délimiteur de débutstart
ne correspond pas sinon il correspond et capture le délimiteur de début et correspond au reste des caractères.Répondre directement à votre question
En utilisant l'approche # 2 (expression délimitée), vous devez sélectionner deux expressions appropriées:
EDE:
[^:/]\/
SDE:
http:
Usage:
Production:
Remarque: cela ne fonctionnera pas avec des délimiteurs identiques.
la source
sed
et tous les autres moteurs suivant le même ordre standard , c'est important en matière d'égalité. N'aecho 'foo 1' | sed -r 's/.|([0-9]+).*/\1/g'
donc pas de match mais leecho 'foo 1' | sed -r 's/([0-9]+).*|./\1/g'
fait.Solution non gourmande pour plus d'un seul personnage
Ce fil est vraiment ancien mais je suppose que les gens en ont encore besoin. Disons que vous voulez tout tuer jusqu'à la toute première occurrence de
HELLO
. Tu ne peux pas dire[^HELLO]
...Donc, une bonne solution implique deux étapes, en supposant que vous pouvez épargner un mot unique que vous n'attendez pas dans l'entrée, par exemple
top_sekrit
.Dans ce cas, nous pouvons:
Bien sûr, avec une entrée plus simple, vous pouvez utiliser un mot plus petit, ou peut-être même un seul caractère.
HTH!
la source
`
, j'utiliserais<$$>
(puisque se$$
développe dans votre ID de processus dans le shell, bien que vous deviez utiliser des guillemets doubles plutôt que des guillemets simples, et que pourrait casser d'autres parties de votre expression rationnelle) ou, si unicode est disponible, quelque chose comme<∈∋>
.perl
oupython
ou une autre langue à la place.perl
le fait de manière moins fragile en une seule ligne ...sed - correspondance non gourmande par Christoph Sieghart
L'astuce pour obtenir une correspondance non gourmande dans sed est de faire correspondre tous les caractères à l'exception de celui qui met fin à la correspondance. Je sais, une évidence, mais j'ai perdu de précieuses minutes dessus et les scripts shell devraient être, après tout, rapides et faciles. Donc, au cas où quelqu'un d'autre en aurait besoin:
Correspondance gourmande
Correspondance non gourmande
la source
Cela peut être fait en utilisant cut:
la source
une autre façon, sans utiliser l'expression régulière, est d'utiliser la méthode des champs / délimiteurs, par exemple
la source
sed
a certainement sa place mais ce n'est pas l'un d'eux!Comme l'a souligné Dee: utilisez simplement
cut
. C'est beaucoup plus simple et beaucoup plus sûr dans ce cas. Voici un exemple où nous extrayons divers composants de l'URL à l'aide de la syntaxe Bash:vous donne:
Comme vous pouvez le voir, cette approche est beaucoup plus flexible.
(tout crédit à Dee)
la source
la source
sed -E interprète les expressions régulières comme des expressions régulières étendues (modernes)
Mise à jour: -E sur MacOS X, -r dans GNU sed.
la source
-E
est propre à BSDsed
et donc à OS X. Liens vers les pages de manuel.-r
apporte des expressions régulières étendues à GNUsed
comme indiqué dans la correction de @ stephancheg. Méfiez-vous lorsque vous utilisez une commande de variabilité connue entre les distributions de 'nix. J'ai appris ça à la dure.-r
option de GNU sed ne change que les règles d'échappement, en fonctionAppendix A Extended regular expressions
du fichier info et de quelques tests rapides; il n'ajoute en fait pas de qualificatif non gourmand (GNU sed version 4.2.1
au moins.)-E
comme une option non documentée pendant un certain temps, mais dans la version 4.2.2.177 , la documentation a été mise à jour pour refléter cela, donc ça-E
va pour les deux maintenant.Il y a encore de l'espoir de résoudre ce problème en utilisant pure (GNU) sed. Malgré cela, ce n'est pas une solution générique dans certains cas, vous pouvez utiliser des "boucles" pour éliminer toutes les parties inutiles de la chaîne comme ceci:
Le seul problème ici est qu'il coupera également le dernier caractère séparateur ('/'), mais si vous en avez vraiment besoin, vous pouvez toujours le remettre une fois la "boucle" terminée, ajoutez simplement cette commande supplémentaire à la fin de la précédente ligne de commande:
la source
Parce que vous avez spécifiquement déclaré que vous essayez d'utiliser sed (au lieu de perl, cut, etc.), essayez de regrouper. Cela contourne l'identifiant non gourmand potentiellement non reconnu. Le premier groupe est le protocole (c'est-à-dire 'http: //', 'https: //', 'tcp: //', etc.). Le deuxième groupe est le domaine:
Si vous n'êtes pas familier avec le regroupement, commencez ici .
la source
Je me rends compte que c'est une ancienne entrée, mais quelqu'un peut la trouver utile. Comme le nom de domaine complet ne peut pas dépasser une longueur totale de 253 caractères, remplacez. * Par. \ {1, 255 \}
la source
Voici comment effectuer de manière robuste une correspondance non gourmande de chaînes multi-caractères à l'aide de sed. Supposons que vous souhaitiez tout changer
foo...bar
pour<foo...bar>
, par exemple, cette entrée:devrait devenir cette sortie:
Pour ce faire, vous convertissez foo et bar en caractères individuels, puis utilisez la négation de ces caractères entre eux:
Au dessus:
s/@/@A/g; s/{/@B/g; s/}/@C/g
est en train de convertir{
et}
en chaînes d'espace réservé qui ne peuvent pas exister dans l'entrée, donc ces caractères sont alors disponibles pour convertirfoo
etbar
vers.s/foo/{/g; s/bar/}/g
convertitfoo
etbar
vers{
et}
respectivements/{[^{}]*}/<&>/g
effectue l'opération que nous voulons - la conversionfoo...bar
en<foo...bar>
s/}/bar/g; s/{/foo/g
convertit{
et}
revient àfoo
etbar
.s/@C/}/g; s/@B/{/g; s/@A/@/g
convertit les chaînes d'espace réservé à leurs caractères d'origine.Notez que ce qui précède ne repose sur aucune chaîne particulière qui n'est pas présente dans l'entrée car il fabrique de telles chaînes à la première étape, et il ne se soucie pas de l'occurrence de toute expression rationnelle particulière que vous souhaitez faire correspondre car vous pouvez utiliser
{[^{}]*}
autant de fois que nécessaire dans l'expression pour isoler la correspondance réelle que vous souhaitez et / ou avec l'opérateur de correspondance numérique seds, par exemple pour remplacer uniquement la 2e occurrence:la source
Vous n'avez pas encore vu cette réponse, voici comment procéder avec
vi
ouvim
:Cela exécute la
vi
:%s
substitution globalement (la fing
), s'abstient de générer une erreur si le modèle n'est pas trouvé (e
), puis enregistre les modifications résultantes sur le disque et se ferme. Les&>/dev/null
empêche l'interface graphique de brièvement clignoter sur l' écran, qui peut être gênant.Je aime utiliser
vi
parfois pour regexes super compliqué, parce que (1) perl estmortmort, (2) vim a un très avancé moteur de regex, et (3) Je suis déjà très familier avec lesvi
expressions rationnelles dans mon édition d'utilisation au jour le jour documents.la source
ne vous embêtez pas, je l'ai eu sur un autre forum :)
la source
/home/one/two/three/
si vous ajoutez un autre/
comme/home/one/two/three/four/myfile.txt
vous correspondront avidementfour
ainsi:/home/one/two/three/four
, la question est sur le non-gourmandsed 's|\(http:\/\/www\.[a-z.0-9]*\/\).*|\1|
fonctionne aussila source
Voici quelque chose que vous pouvez faire avec une approche en deux étapes et un awk:
J'espère que cela pourra aider!
la source
Une autre version sed:
Il correspond
/
suivi d'un caractère alphanumérique (donc pas d'une autre barre oblique) ainsi que du reste des caractères jusqu'à la fin de la ligne. Ensuite, il le remplace par rien (c'est-à-dire le supprime.)la source
"[[:alnum:]]"
, non"[:alphanum:]"
.