Получить последнее поле с помощью awk substr

101

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

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

который отлично работает.
Однако я жестко кодирую, $5что было бы неверно, если бы мой ввод имел следующую структуру:

/home/parent/child1/child2/filename

Таким образом, общее решение требует всегда брать последнее поле (которое будет именем файла).

Есть ли простой способ сделать это с помощью функции awk substr?

Мари
источник
2
как кто-то указал, что использование basenameявляется официальным способом сделать это, использование awkдля этого нехорошо, если говорить легкомысленно. : D
Kashyap

Ответы:

209

Используйте тот факт, что 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
fedorqui 'ТАК, хватит вредить'
источник
3
Работает отлично. Я не думал о переменной $ NF. Спасибо за незамедлительный простой и эффективный ответ.
Mari
6
Для предпоследнего используйте $(NF-1).
Итачи
1
Писал скрипт для работы с некоторыми командами докеров, и это помогло. Спасибо!
Harlin
31

В этом случае лучше использовать 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 01
это сработало для меня при получении от ввода по трубопроводу. Совсем забыл про 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 года, но ... вам следует подумать о расширении параметров, оно встроено и быстрее.

если ваш ввод находится в переменной, скажем, $ 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
Adriano_Pinaffo
источник
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'
SARATH
источник
1
На данный момент никто не поддержал этот ответ, вероятно, потому, что он сравнительно уродливый :)
Йосип Родин