2013-04-22 7 views
6

Przepraszam za kulawe pytanie o bash, ale wydaje mi się, że nie jestem w stanie go rozwiązać.Bash ostatni indeks z

mam następujący prosty przykład:

  • mam zmienna jak artifact-1.2.3.zip

  • chciałbym uzyskać podnapis pomiędzy łącznikiem a ostatni indeks kropki (zarówno wyłączne).

Moje umiejętności bash nie są zbyt silne. Mam następujący:

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

Produkcja:

1.2.3.zip 

Jak mogę usunąć .zip część jak dobrze?

Odpowiedz

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

#wzór” usuwa wzór tak długo, jak to pasuje do zaczynają o $a. Składnia wzoru jest podobna do tej używanej przy dopasowywaniu nazwy pliku. W naszym przypadku

  • * jest dowolną sekwencją znaków.
  • - oznacza dosłowny kreska.
  • W ten sposób #*- pasuje do wszystkiego, łącznie z pierwszą kreską.
  • Zatem ${a#*-} rozszerza się cokolwiek $a rozwinie się, oprócz tego artifact- zostanie usunięty z ekspansji pozostawiając nas z 1.2.3.zip.

Podobnie „%wzór” usuwa wzór o ile jest on zgodny z końcem rozprężania. W naszym przypadku

  • . dosłownym kropka.
  • * dowolna sekwencja znaków.
  • Tak więc %.* to wszystko, w tym kropka ostatnia dot do końca łańcucha.
  • Zatem jeśli $a rozszerzy się do 1.2.3.zip, , wówczas ${a%.*} rozszerzy się do 1.2.3.

Wykonane zadanie.

Zawartość strony człowieka za to w następujący sposób (przynajmniej na moim komputerze, 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

Uznanie @ X4D za szczegółową odpowiedź. Nadal uważam, że ludzie powinni jednak RTFM. Jeśli nie rozumieją instrukcji, , a następnie opublikuj kolejne pytanie.

+0

Ładne i proste, dziękuję! – carlspring

+5

Wszelkie wyjaśnienia lub powiązane dokumenty wymienione tutaj byłyby lepsze. – Judking

+0

RTFM. Aby być uczciwym strona podręcznika jest bardzo duża. Poszukaj dwóch kolejnych skrótów w tym pliku, a znajdziesz się w prawym obszarze (polecenie '/ ## 'w _less_) – bobbogo

0

myślę, że można to zrobić:

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

substring=${string:0:4} 

Ostatnim krokiem usuwa ostatnie 4 znaki z łańcucha. Więcej informacji na temat here.

+0

+1: Chociaż spowoduje to powiązanie mnie z trzyliterowym rozszerzeniem. Przyjmuję odpowiedź od bobbogo. Dzięki! – carlspring

+0

Dzięki, nie ma problemu, to nie jest bardzo przenośne rozwiązanie, ale lubię prostotę :). Rozwiązanie Bobbogo jest drogą do zrobienia. – James

3

Korzystanie cecha Bash RegEx:

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

Sekcja bash mężczyzna stron zatytułowanych "Zmienna Zmiana" opisuje za pomocą ${var#pattern}, ${var##pattern}, ${var%pattern} i ${var%%pattern}.

Zakładając, że masz zmienną o nazwie filename np

filename="artifact-1.2.3.zip" 

następnie następujące ekstrakcje są w oparciu o wzorce:

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

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

Dlaczego używam ## zamiast #?

Jeżeli nazwa pliku może ewentualnie zawierać łączniki wewnątrz, takich jak:

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

następnie porównać dwa następujące podstawienia:

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

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

Gdy po ekstrakcji wersję i rozszerzenie, aby wyizolować wersję użyj:

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

Spróbuję też tego! Dziękuję za szczegółowy opis. – carlspring