Yanıtlar:
basename
GNU coreutils'den bu işi yapmanıza yardımcı olabilir:
$ basename /root/video.mp4
video.mp4
Dosyanın uzantısını zaten biliyorsanız, kaldırmak basename
için sözdizimini kullanarak başlatabilirsiniz basename NAME [SUFFIX]
:
$ basename /root/video.mp4 .mp4
video
Ya da başka bir seçenek, son noktadan sonra her şeyi kullanarak sed
şunları kesmek olabilir :
$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old
Aşağıdaki yollardan birini kullanın:
out_file="${in_file##*/}"
out_file="$(basename $in_file)"
out_file="$(echo $in_file | sed 's=.*/==')"
out_file="$(echo $in_file | awk -F"/" '{ print $NF }')"
ps. \(.*\.\)
İfadenizde başlangıçtan noktaya ( /root/video.
) kadar dizeyle eşleştiğinden aynı dizeyi alırsınız ve ardından .mp4
orijinal dizenizdeki ile aynı olanı manuel olarak eklersiniz . Bunun s=.*\([^/]*\)=\1=
yerine kullanmalısınız .
Güncelleme: (Birincisi düzeltildi)
Uzantısız tek dosya adını almak için şunları yapabilirsiniz:
out_file="$(echo $in_file | sed 's=.*/==;s/\.[^.]*$/.new_ext/')"
out_file="$(echo $in_file | sed 's=\([^/]*\)\.[^./]*$=\1.new_ext=')"
out_file="$(echo $in_file | awk -F"/" '{ gsub (/\.[^/.]*$/,".new_ext",$NF);print $NF }'
my.file.tar.gz
.
sed
ve awk
. Sabit. Teşekkür ederim.
Normal ifade kullanmanın temellerinden biri, joker kartı belirtirken desenlerin doğası gereği açgözlü olmasıdır. @UloBasEI tarafından önerilen cevap kesinlikle çalışan bir cevap olsa da, basename komutunun da kullanılmasını gerektirir. @Shixons'un orijinal sorusu sadece sed kullanarak bir çözüm ister.
Devam etmeden önce, hangi sed sürümünün hedef olduğunu bilmek her zaman yararlıdır. BSD varsayıyorum (OSX ile birlikte gönderildiği gibi).
Her şeyden önce, orijinal soruda önerilen desen işe yaramaz çünkü giriş dizesinin başlangıcından son noktaya kadar olan her şeyi yakalar. Çapa olmadan, bu arama her şeyi soldan sağa yutacaktır. Bu nedenle "/ 1" uyumlu desen, son noktaya kadar ve son noktaya kadar olan her şeydir. Birden çok noktalı bir dosya adı bile tamamen yutulacaktır. İstenen sonuç hiç değil.
İlk adım, kalıpları tanımlamak için bir strateji oluşturmaktır. Burada, dosya adının solundaki her şeyden kurtulmak istiyorsunuz (daha sonra uzantıyla ilgileneceğiz):
out_file="$(echo $in_file | sed 's/^\(\/.*\/\)*.*/\1/')"
Arama dizenin başından itibaren eşleşir. "/.*" sıfır veya daha fazla kez eşleşir ve daha sonra her şeyi siler. Eşleşen desenleri "\ 1" ile yazdırıyoruz. Global olarak arama yapmıyoruz; ^ çapasını belirterek dizenin başından itibaren arıyoruz.
Parantezlerden kaçmak zorunda kalmamak için "-E" seçeneğini etkinleştirerek daha iyi netlik elde ederiz:
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*.*/\1/')"
Şimdi sol tarafta bir parçamız var. Parçayı sağa ekleyelim. Sol parçayı desen olarak tutmamız gerektiğini unutmayın, çünkü sıfır veya daha fazla kez görünmesini bu şekilde belirleyebiliriz. Şimdi tek yaptığımız, sağdaki parça için bir model eklemek:
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)/\2/')"
Yalnızca ikinci eşleşmeyi yazdırırız, böylece dosya adı dışında her şeyi atarız. Ancak yine de dosya adı uzantısını kaldırmamız gerekiyor.
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2/')"
Sondaki "$" isteğe bağlıdır.
Son olarak, şu şekilde revize ettiğiniz yeni uzantıyı eklemek için:
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2.mp4/')"
Ek bir optimizasyon, göreli yolları işlemek için ilk eğik çizgiyi isteğe bağlı yapmaktır:
out_file="$(echo $in_file | sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2.mp4/')"
Basename yerine bir sed kalıbı ararken tembel olarak bu soruya rastladım . Bu komutu yüklü olmayan soyulmuş bir sistem üzerinde çalışıyorum.
sed 's/\.[^.]*$//'
, (gizli).filename
ve.
ve..
dizinler için başarısız olacaktır