Jak mogę uzyskać tylko nazwę pliku za pomocą sed? Mam to
out_file=$(echo $in_file|sed "s/\(.*\.\).*/\1mp4/g")
Ale ja też dostaję ścieżkę /root/video.mp4
i chcę tylko video.mp4
.
basename
z jądra GNU mogą pomóc w wykonaniu tej pracy:
$ basename /root/video.mp4
video.mp4
Jeśli znasz już rozszerzenie pliku, możesz go wywołać, basename
używając składni basename NAME [SUFFIX]
, aby go usunąć:
$ basename /root/video.mp4 .mp4
video
Inną opcją byłoby wycinanie wszystkiego po ostatniej kropce za pomocą sed
:
$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old
sed 's/\.[^.]*$//'
jak trzeba, nie powiedzie się na (ukryty).filename
i.
i..
katalogiNajłatwiejszym rozwiązaniem jest usunięcie wszystkiego do ostatniego pojawienia się
/
:echo /root/video.mp4 | sed 's/.*\///'
źródło
Użyj dowolnego z poniższych sposobów:
ps. Otrzymujesz ten sam ciąg znaków, ponieważ w swojej instrukcji
\(.*\.\)
pasuje do ciągu od początku do kropki (/root/video.
), a następnie dodajesz ręcznie,.mp4
który jest taki sam jak w swoim oryginalnym ciągu. Zamiast tego powinieneś użyćs=.*\([^/]*\)=\1=
.Aktualizacja: (Pierwszy jest teraz naprawiony)
Aby uzyskać jedyną nazwę pliku bez rozszerzenia, możesz:
źródło
my.file.tar.gz
.sed
iawk
. Naprawiony. Dziękuję Ci.Jedną z podstaw używania wyrażenia regularnego jest to, że przy określaniu symbolu wieloznacznego wzorce są z natury chciwe. Chociaż odpowiedź zaproponowana przez @uloBasEI jest z pewnością działającą odpowiedzią, wymaga także użycia polecenia basename. Oryginalne pytanie z @Shixons wymaga rozwiązania wykorzystującego tylko sed.
Przed kontynuowaniem zawsze warto wiedzieć, która wersja sed jest celem. Zakładam, że BSD (jak dostarczane z OSX).
Po pierwsze, wzór zaproponowany w pierwotnym pytaniu nie działa, ponieważ przechwytuje wszystko od początku ciągu wejściowego do ostatniej kropki włącznie. Bez kotwic wyszukiwanie to pochłonie wszystko od lewej do prawej. Dopasowany wzorzec „/ 1” to zatem wszystko do ostatniej kropki włącznie. Nawet nazwa pliku z wieloma kropkami zostanie połknięta w całości. Wcale nie pożądany wynik.
Pierwszym krokiem jest ustanowienie strategii identyfikacji wzorców. Tutaj chcesz pozbyć się wszystkiego po lewej stronie nazwy pliku (zajmiemy się rozszerzeniem później):
Wyszukiwanie pasuje do początku ciągu. Dopasowuje wzorzec „/.*” zero lub więcej razy i usuwa wszystko później. Dopasowane wzory drukujemy za pomocą „\ 1”. Nie szukamy globalnie; szukamy od początku łańcucha, określając ^ anchor.
Uzyskujemy lepszą przejrzystość, włączając opcję „-E”, dzięki czemu nie musimy uciekać od nawiasów:
Więc teraz mamy część po lewej stronie. Dodajmy część po prawej stronie. Zauważ, że musimy zachować lewą część jako wzór, ponieważ w ten sposób możemy określić, że pojawia się zero lub więcej razy. Teraz dodajemy wzór dla części po prawej:
Drukujemy tylko drugie dopasowanie, odrzucając w ten sposób wszystko oprócz nazwy pliku. Ale nadal musimy usunąć rozszerzenie nazwy pliku.
„$” Na końcu jest opcjonalne.
Na koniec, aby dodać nowe rozszerzenie, które właśnie zmieniacie:
Dodatkową optymalizacją jest uczynienie pierwszego ukośnika do przodu opcjonalnym do obsługi ścieżek względnych:
Natknąłem się na to pytanie, będąc leniwym, szukając wzoru sed, który zastąpiłby basename . Pracuję na systemie okrojonym, w którym nie zainstalowano tego polecenia.
źródło