Awk substratı kullanarak son alanı alın


105

awkDosyanın mutlak yolu verilen bir dosyanın adını almaya çalışıyorum .
Örneğin, giriş yolu verildiğinde /home/parent/child/filenamealmak filename istediğim şey denedim:

awk -F "/" '{print $5}' input

hangi mükemmel çalışıyor.
Bununla birlikte, girdim $5aşağıdaki yapıya sahipse yanlış olacak olan sabit kodlamayım :

/home/parent/child1/child2/filename

Yani genel bir çözüm her zaman son alanı (dosya adı olacaktır) almayı gerektirir .

Bunu awk substr işleviyle yapmanın basit bir yolu var mı?


2
basenameBunu yapmanın resmi yolu kullanmanın işaret ettiği gibi , bunun awkiçin kullanmak hafife almak iyi değildir. : D
Kashyap

Yanıtlar:


215

awkAlanlardaki çizgileri, tanımlayabileceğiniz bir alan ayırıcısına göre bölen gerçeğini kullanın . Bu nedenle, alan ayırıcısını /size tanımlayarak şunu söyleyebilirsiniz:

awk -F "/" '{print $NF}' input

NFgeçerli kaydın alan sayısını ifade ettiği gibi , $NFyazdırma, sonuncuyu yazdırmak anlamına gelir.

Öyleyse şöyle bir dosya verildi:

/home/parent/child1/child2/child3/filename
/home/parent/child1/child2/filename
/home/parent/child1/filename

Çıktı şu olacaktır:

$ awk -F"/" '{print $NF}' file
filename
filename
filename

3
Mükemmel çalışıyor. $ NF değişkenini düşünmedim. Hemen basit ve etkili cevabınız için teşekkürler.
Mari

6
Sonuncusu için kullanın $(NF-1).
Itachi

1
Bazı docker komutlarıyla çalışmak için bir komut dosyası yazıyordu ve bu hile yaptı. Teşekkürler!
Harlin

31

Bu durumda aşağıdakiler basenameyerine kullanmak daha iyidir awk:

 $ basename /home/parent/child1/child2/filename
 filename

4
@Mari FYI dirname bunun tersini yapar ve dosya yolunu çıkarmaz.
Chris Seymour

5

Diğer bir seçenek de bash parametre ikamesi kullanmaktır .

$ foo="/home/parent/child/filename"
$ echo ${foo##*/}
filename
$ foo="/home/parent/child/child2/filename"
$ echo ${foo##*/}
filename

5

Bir Perl çözümüne açıksanız, burada fedorqui'nin awk çözümüne benzer bir çözüm:

perl -F/ -lane 'print $F[-1]' input

-F/belirtir /alan ayırıcı olarak
$F[-1]son öğe olur @Fotomatik bölme dizisi


1
Teşekkürler. Bu, son bir alan olmama yardımcı oldu. perl -F "/" -lane 'baskı $ F [-2]' girdisi
riderchap

bu, borulu girişten alırken benim için çalıştı. Perl'i tamamen unuttum.
Chris

3

Baz adı cevabına bir yorum olmalı ama yeterli noktam yok.

Çift tırnak kullanmazsanız basename, boşluk karakterinin olduğu yol ile çalışmaz:

$ basename /home/foo/bar foo/bar.png
bar

tırnak işaretleriyle tamam ""

$ basename "/home/foo/bar foo/bar.png"
bar.png

dosya örneği

$ cat a
/home/parent/child 1/child 2/child 3/filename1
/home/parent/child 1/child2/filename2
/home/parent/child1/filename3

$ while read b ; do basename "$b" ; done < a
filename1
filename2
filename3

3

Bunun 3 yıl geciktiğimi biliyorum ama .... parametre genişletmeyi düşünmelisiniz, yerleşik ve daha hızlı.

eğer girişiniz bir var içindeyse, diyelim ki $ var1, sadece yapın ${var1##*/}. Aşağı bak

$ var1='/home/parent/child1/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/child3/filename'
$ echo ${var1##*/}
filename

2

5 yıl gecikmiş gibi biliyorum, tüm teklifler için teşekkürler, bunu şu şekilde yapıyordum:

$ echo /home/parent/child1/child2/filename | rev | cut -d '/' -f1 | rev
filename

Daha iyi davranışlar olduğunu fark etmekten memnun oldum


-1

Ayrıca kullanabilirsin:

    sed -n 's/.*\/\([^\/]\{1,\}\)$/\1/p'

veya

    sed -n 's/.*\/\([^\/]*\)$/\1/p'

1
Bu noktada kimse bu cevaba olumlu oy vermedi, çünkü muhtemelen kıyaslanamayacak kadar çılgınca :)
Josip Rodin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.