Отримати останнє поле, використовуючи підстроку awk


99

Я намагаюся використати, awkщоб отримати ім'я файлу з урахуванням абсолютного шляху до файлу.
Наприклад, коли мені вказали вхідний шлях, який /home/parent/child/filenameя хотів би отримати, filenameя спробував:

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

що працює ідеально.
Однак я жорстко кодую, $5що було б неправильно, якщо моє введення має таку структуру:

/home/parent/child1/child2/filename

Отже, загальне рішення вимагає завжди приймати останнє поле (яке буде іменем файлу).

Чи існує простий спосіб зробити це за допомогою функції substr sub?


2
як хтось зазначав, використання basename- це офіційний спосіб зробити це, використовувати awkдля цього - не добре, якщо говорити легковажно. : D
Кашьяп

Відповіді:


206

Використовуйте той факт, що awkрозділяє рядки в полях на основі роздільника полів, який ви можете визначити. Отже, визначаючи роздільник поля, /ви можете сказати:

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

що NFстосується кількості полів поточного запису, друк $NFозначає друк останнього.

Отже, отримавши такий файл:

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

Це буде результат:

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

3
Це чудово працює. Я не думав про змінну $ NF. Дякуємо за Вашу негайну просту та ефективну відповідь.
Mari

6
Для передостаннього використовуйте $(NF-1).
Ітачі

1
Писав сценарій для роботи з деякими командами докера, і це зробило трюк. Дякую!
Харлін,

30

У цьому випадку краще використовувати basenameзамість awk:

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

4
@Mari FYI dirname робить навпаки і позбавляє файл не шляху.
Кріс Сеймур,


5

Якщо ви відкриті для рішення Perl, ось таке, подібне до рішення awk fedorqui:

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

-F/вказує, /як роздільник поля
$F[-1]є останнім елементом у @Fмасиві авторозділення


1
Дякую. Це допомогло мені отримати останнє, але одне поле. perl -F "/" -lane 'print $ F [-2]' input
riderchap

це спрацювало для мене при отриманні з трубопровідного вводу. Зовсім забув про perl.
Крістофер

3

Це повинен бути коментар до відповіді на базове ім’я, але мені недостатньо суті.

Якщо ви не використовуєте подвійні лапки, basenameне буде працювати з шляхом, де є пробіл:

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

добре з цитатами ""

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

приклад файлу

$ 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

Я знаю, що на це я запізнився на 3 роки, але .... Вам варто подумати про розширення параметрів, воно вбудоване та швидше.

якщо ви вводите в var, скажімо, $ var1, просто зробіть ${var1##*/}. Подивіться нижче

$ 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 років, я знаю, дякую за всі пропозиції, я робив це наступним чином:

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

Радий помітити, що є кращі манери


-1

Ви також можете використовувати:

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

або

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

1
На даний момент ніхто не проголосував за цю відповідь, мабуть, тому, що вона порівняно мізерна :)
Йосип Роден,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.