Nhận trường cuối cùng bằng cách sử dụng awk substr


99

Tôi đang cố gắng sử dụng awkđể lấy tên của tệp cho đường dẫn tuyệt đối đến tệp.
Ví dụ: khi được cung cấp đường dẫn đầu vào mà /home/parent/child/filenametôi muốn lấy, filename tôi đã thử:

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

hoạt động hoàn hảo.
Tuy nhiên, tôi đang viết mã cứng $5sẽ không chính xác nếu đầu vào của tôi có cấu trúc sau:

/home/parent/child1/child2/filename

Vì vậy, một giải pháp chung yêu cầu luôn lấy trường cuối cùng (sẽ là tên tệp).

Có cách nào đơn giản để thực hiện việc này với hàm awk substr không?


2
như ai đó đã chỉ ra sử dụng basenamelà cách chính thức để làm điều này, sử dụng awkcho điều này là không tốt nếu nói nhẹ nó. : D
Kashyap

Câu trả lời:


206

Sử dụng thực tế là awkphân chia các dòng trong các trường dựa trên dấu phân tách trường mà bạn có thể xác định. Do đó, xác định dấu phân cách trường /bạn có thể nói:

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

như NFđề cập đến số lượng trường của bản ghi hiện tại, in $NFcó nghĩa là in cuối cùng.

Vì vậy, đã đưa ra một tệp như thế này:

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

Đây sẽ là đầu ra:

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

3
Nó hoạt động hoàn hảo. Tôi không nghĩ về biến $ NF. Cảm ơn câu trả lời đơn giản và hiệu quả ngay lập tức của bạn.
Mari,

6
Đối với bút chì, hãy sử dụng $(NF-1).
Itachi

1
Đang viết một tập lệnh để làm việc với một số lệnh của docker và điều này đã thực hiện được mẹo. Cảm ơn!
Harlin

30

Trong trường hợp này, tốt hơn là sử dụng basenamethay vì awk:

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

4
@Mari FYI dirname làm ngược lại và tách tệp không phải đường dẫn.
Chris Seymour,

5

Một tùy chọn khác là sử dụng bash thay thế tham số .

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

5

Nếu bạn đang sử dụng giải pháp Perl, đây là một giải pháp tương tự như giải pháp awk của fedorqui:

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

-F/chỉ định /làm dấu phân tách trường
$F[-1]là phần tử cuối cùng trong @Fmảng autosplit


1
Cảm ơn. Điều này đã giúp tôi đến cuối cùng trừ một lĩnh vực. perl -F "/" -lane 'print $ F [-2]' đầu vào
riderchap

điều này đã làm việc cho tôi khi nhận từ đầu vào đường ống. Hoàn toàn quên về perl.
Christopher

3

Nó phải là một nhận xét cho câu trả lời tên cơ sở nhưng tôi không đủ điểm.

Nếu bạn không sử dụng dấu ngoặc kép, basenamesẽ không hoạt động với đường dẫn có ký tự khoảng trắng:

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

ok với dấu ngoặc kép ""

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

tập tin ví dụ

$ 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

Tôi biết tôi đã muộn 3 năm về điều này nhưng .... bạn nên xem xét việc mở rộng tham số, nó được tích hợp sẵn và nhanh hơn.

nếu đầu vào của bạn ở dạng var, giả sử $ var1, chỉ cần làm ${var1##*/}. Nhìn bên dưới

$ 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

Như đã muộn 5 năm, tôi biết, cảm ơn vì tất cả các đề xuất, tôi đã từng làm theo cách sau:

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

Rất vui khi nhận thấy có những cách cư xử tốt hơn


-1

Bạn cũng có thể dùng:

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

hoặc là

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

1
Tại thời điểm này không ai upvoted câu trả lời này, có lẽ bởi vì nó có thể so sánh fugly :)
Josip Rodin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.