2010-06-16 14 views
3

Salutations!Bash: rogner un paramètre des deux extrémités

Ce sont connaissent bien les modèles d'extension des paramètres de Bash:

$ {paramètre # mot}, $ {paramètre ## mot}

et

$ {paramètre mot% }, $ {paramètre %% mot}

Je dois hacher une partie depuis le début et une autre partie depuis la fin du paramètre. Pourriez-vous conseiller quelque chose pour moi s'il vous plaît?

+0

vous obtiendriez beaucoup de meilleures réponses si vous fournissez l'entrée d'échantillon et la sortie désirée – SiegeX

+0

J'ai un chemin "/.../ABC/abc.txt" et je veux obtenir le nom du dossier d'hôte pour le dossier "abc. txt ", qui dans cet exemple est" ABC ". –

Répondre

0

Je ne sais pas qu'il existe un moyen facile de faire cela sans recourir à des sous-coquilles, quelque chose que vous voulez probablement éviter pour l'efficacité. Je voudrais simplement utiliser:

> xx=hello_there 
> yy=${xx#he} 
> zz=${yy%re} 
> echo ${zz} 
llo_the 

Si vous n'êtes pas démenait sur l'efficacité et que vous voulez juste un one-liner:

> zz=$(echo ${xx%re} | sed 's/^he//') 
> echo ${zz} 
llo_the 

Gardez à l'esprit que cette deuxième méthode commence sous-coquilles - ce n'est pas quelque chose Je ferais beaucoup de si votre script doit courir vite.

+0

Merci beaucoup! J'utilise actuellement la variante de votre première méthode: DIRNAME = "./ ABC/abc.txt" DIRNAME = $ {DIRNAME #. /} DIRNAME = $ {DIRNAME%/*. Txt} Mais je ne sais pas comprendre pourquoi cette méthode implique des sous-coquilles ... –

+0

La première méthode n'implique pas de sous-coquilles, c'est seulement la seconde qui fait cela. Je vais clarifier. – paxdiablo

+0

Est-il possible d'incorporer deux lignes de votre première méthode à une ligne? –

1

Si vous utilisez la version Bash> = 3.2, vous pouvez utiliser une expression régulière correspondant à un groupe de capture pour récupérer la valeur dans une commande:

$ path='/xxx/yyy/zzz/ABC/abc.txt' 
$ [[ $path =~ ^.*/([^/]*)/.*$ ]] 
$ echo ${BASH_REMATCH[1]} 
ABC 

Cela équivaudrait à:

$ path='/xxx/yyy/zzz/ABC/abc.txt' 
$ path=$(echo "$path" | sed 's|^.*/\([^/]*\)/.*$|\1|p') 
$ echo $path 
ABC 
0

Cette solution utilise ce que demande Andrey et n'utilise aucun outil externe. Stratégie: Utiliser l'expansion du paramètre% pour supprimer le nom de fichier, utilisez alors le ## pour supprimer tous, mais le dernier répertoire:

$ path=/path/to/my/last_dir/filename.txt 

$ dir=${path%/*}  

$ echo $dir 
/path/to/my/last_dir 

$ dir=${dir##*/} 

$ echo $dir 
last_dir 
0

Je recommande vivement d'y aller avec des tableaux de bash que leur performance est un peu plus de 3 fois plus rapide que correspondance d'expression régulière.

$ path='/xxx/yyy/zzz/ABC/abc.txt' 
$ IFS='/' arr=($path) 
$ echo ${arr[${#arr[@]}-2]} 
ABC 

Cela fonctionne en disant bash que chaque élément de la matrice est séparée par une barre oblique / via IFS='/'. Nous accédons à l'avant-dernier élément du tableau en déterminant d'abord combien d'éléments sont dans le tableau via ${#arr[@]} puis en soustrayant 2 et en l'utilisant comme index pour le tableau.