J'ai une chaîne comme first url, second url, third url
Et je souhaite extraire uniquement le url
après le mot second
dans le terminal OS X (uniquement la première occurrence). Comment puis-je le faire?
Dans mon éditeur préféré J'ai utilisé l'expression régulière /second (url)/
et utilisé $1
Pour l'extraire, je ne sais tout simplement pas comment le faire dans le Terminal.
Gardez à l'esprit que url
est une URL réelle, je vais utiliser l'une de ces expressions pour la faire correspondre: Regex pour correspondre à l'URL
echo 'first url, second url, third url' | sed 's/.*second//'
Edit: j'ai mal compris. Mieux:
echo 'first url, second url, third url' | sed 's/.*second \([^ ]*\).*/\1/'
ou:
echo 'first url, second url, third url' | Perl -nle 'm/second ([^ ]*)/; print $1'
La tuyauterie vers un autre processus (comme "sed" et "Perl" suggéré ci-dessus) peut être très coûteuse, en particulier lorsque vous devez exécuter cette opération plusieurs fois. Bash prend en charge l'expression rationnelle:
De la même manière que vous extrayez des correspondances dans votre éditeur préféré en utilisant $1
, $2
, etc., Bash remplit le $BASH_REMATCH
tableau avec toutes les correspondances.
Dans votre exemple particulier:
str="first usr1, second url2, third url3"
if [[ $str =~ (second )([^,]*) ]]; then echo "match: '${BASH_REMATCH[2]}'"; else echo "no match found"; fi
Production:
match: 'url2'
Plus précisément, =~
prend en charge les expressions régulières étendues telles que définies par POSIX , mais avec spécifique à la plate-forme extensions (dont l'étendue varie et peuvent être incompatibles).
Sur les plateformes Linux (GNU userland), voir man grep
; sur les plates-formes macOS/BSD, voir man re_format
.
Dans l'autre réponse, à condition que vous restiez avec tout après l'URL souhaitée. Je vous propose donc la solution suivante.
echo 'first url, second url, third url' | sed 's/.*second \(url\)*.*/\1/'
Sous sed, vous regroupez une expression en échappant aux parenthèses qui l'entourent (norme POSIX).
En essayant ceci, ce que vous avez probablement oublié était le -E
argument pour sed
.
De sed --help
:
-E, -r, --regexp-extended
use extended regular expressions in the script
(for portability use POSIX -E).
Vous n'avez pas besoin de modifier votre expression régulière de manière significative, mais vous devez ajouter .*
pour correspondre avidement autour de lui pour supprimer l'autre partie de la chaîne.
Cela fonctionne bien pour moi:
echo "first url, second url, third url" | sed -E 's/.*second (url).*/\1/'
Production:
url
Dans lequel la sortie "url" est en fait la deuxième instance de la chaîne. Mais si vous savez déjà qu'il est formaté entre virgule et espace, et que vous n'autorisez pas ces caractères dans les URL, alors l'expression régulière [^,]*
devrait être bien.
En option:
echo "first http://test.url/1, second ://test.url/with spaces/2, third ftp://test.url/3" \
| sed -E 's/.*second ([a-zA-Z]*:\/\/[^,]*).*/\1/'
Qui sort correctement:
://example.com/with spaces/2