2013-04-22 13 views
6

Ci scusiamo per la domanda di lash bash, ma non riesco a riuscire a risolverlo.Bash ultimo indice di

Ho il seguente caso semplice:

  • Ho variabile come artifact-1.2.3.zip

  • vorrei ottenere un sub-corda tra il trattino e l'ultimo indice del punto (entrambi in esclusiva).

Le mie abilità di bash non sono troppo forti. Ho il seguente:

a="artifact-1.2.3.zip"; b="-"; echo ${a:$(($(expr index "$a" "$b" + 1) - $(expr length "$b")))} 

Produrre:

1.2.3.zip 

Come posso rimuovere la parte .zip come bene?

risposta

4
$ a="artifact-1.2.3.zip"; a="${a#*-}"; echo "${a%.*}" 

#modello’ rimuove modello purché corrisponda al inizio di $a. La sintassi del modello è simile a quella utilizzata nella corrispondenza del nome file. Nel nostro caso,

  • * è qualsiasi sequenza di caratteri.
  • - significa un trattino letterale.
  • Così #*- corrisponde a tutto, incluso il primo trattino.
  • Così ${a#*-} espande a qualsiasi $a sarebbe espandersi, tranne che artifact- viene rimosso dalla espansione, lasciandoci con 1.2.3.zip.

Allo stesso modo, ‘%modello’ rimuove modello purché corrisponda al fine dell'espansione. Nel nostro caso,

  • . un punto letterale.
  • * qualsiasi sequenza di caratteri.
  • Così %.* è tutto compreso lo ultimo punto fino alla fine della stringa.
  • Quindi se $a si espande a 1.2.3.zip, , quindi ${a%.*} si espande a 1.2.3.

Lavoro svolto.

Il contenuto pagina man di questo è la seguente (almeno sulla mia macchina, YMMV):

 
     ${parameter#word} 
     ${parameter##word} 
       The word is expanded to produce a pattern just as in pathname 
       expansion. If the pattern matches the beginning of the value of 
       parameter, then the result of the expansion is the expanded 
       value of parameter with the shortest matching pattern (the ``#'' 
       case) or the longest matching pattern (the ``##'' case) deleted. 
       If parameter is @ or *, the pattern removal operation is applied 
       to each positional parameter in turn, and the expansion is the 
       resultant list. If parameter is an array variable subscripted 
       with @ or *, the pattern removal operation is applied to each 
       member of the array in turn, and the expansion is the resultant 
       list. 

     ${parameter%word} 
     ${parameter%%word} 
       The word is expanded to produce a pattern just as in pathname 
       expansion. If the pattern matches a trailing portion of the 
       expanded value of parameter, then the result of the expansion is 
       the expanded value of parameter with the shortest matching pat- 
       tern (the ``%'' case) or the longest matching pattern (the 
       ``%%'' case) deleted. If parameter is @ or *, the pattern 
       removal operation is applied to each positional parameter in 
       turn, and the expansion is the resultant list. If parameter is 
       an array variable subscripted with @ or *, the pattern removal 
       operation is applied to each member of the array in turn, and 
       the expansion is the resultant list. 

HTH!

EDIT

Complimenti a @ X4D per la risposta dettagliata. Pensa ancora che la gente dovrebbe RTFM però. Se non capiscono il manuale, quindi pubblica un'altra domanda.

+0

Bello e semplice, grazie! – carlspring

+5

Qualsiasi spiegazione o documento correlato elencato qui sarebbe meglio. – Judking

+0

RTFM. Per essere onesti, la pagina man è molto grande. Cerca due hash consecutivi in ​​quel file e sarai nella zona giusta (comando '/ ##' in _less_) – bobbogo

0

penso che si può fare questo:

string=${a="artifact-1.2.3.zip"; b="-"; echo ${a:$(($(expr index "$a" "$b" + 1) - $(expr length "$b")))}} 

substring=${string:0:4} 

L'ultimo passo di rimuovere gli ultimi 4 caratteri dalla stringa. Ci sono altre informazioni su here.

+0

+1: Sebbene mi legherà a un'estensione di tre lettere. Accetterò la risposta di bobbogo. Grazie! – carlspring

+0

Grazie, nessun problema, non è una soluzione molto portatile, ma mi piace mantenere le cose semplici :). La soluzione di Bobbogo è la strada da percorrere. – James

3

Utilizzando la funzione di Bash RegEx:

>str="artifact-1.2.3.zip" 
[[ "$str" =~ -(.*)\.[^.]*$ ]] && echo ${BASH_REMATCH[1]} 
21

La sezione pagina bash man dal titolo "variabile di sostituzione" descrive usando ${var#pattern}, ${var##pattern}, ${var%pattern} e ${var%%pattern}.

Supponendo di avere una variabile chiamata filename, per esempio,

filename="artifact-1.2.3.zip" 

poi, i seguenti sono estrazioni modello-base:

% echo "${filename%-*}" 
artifact 

% echo "${filename##*-}" 
1.2.3.zip 

Perché io uso ## invece di #?

Se il nome file potrebbe contenere trattini all'interno, quali:

filename="multiple-part-name-1.2.3.zip" 

poi confronta le due seguenti sostituzioni:

% echo "${filename#*-}" 
part-name-1.2.3.zip 

% echo "${filename##*-}" 
1.2.3.zip 

Dopo aver estratto la versione ed estensione, per isolare la versione, utilizzare:

% verext="${filename##*-}" 
% ver="${verext%.*}" 
% ext="${verext##*.}" 
% echo $ver 
1.2.3 
% echo $ext 
zip 
+0

Lo proverò anche io! Grazie per la descrizione dettagliata. – carlspring